Trip Expense Manager App .Net MAUI Blazor Hybrid + SQLite | Step by Step Build (From Scratch to End)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys I'm back with another video and in this video we are going to build an app for iPhone and Android using Dot and Maui and this time with blazer hybrid so this is the app we are going to build this is an uh an app using which we can manage our expenses basically when uh the trip and travel expenses so it is named as tripex which is strip expense manager so this is the first screen login screen and if we are opening it for the first time we can use the sign up we can add a name username password so let's add username sorry my name then password then sign up so I just added this to check and now we can come here and this is the main screen we are going to see so here you can see we have this nice header this user icon then we don't have any trip added yet this is the nice uh tab bar bottom tab bar let's do the same thing on Android so you will see that there are some slightly small differences so let me use the same thing here by Prince AP and the same password sign up okay now you see these are the two screens side by side so this looks similar with some a small platform differences for example the tab bar it shows the main title in the center on iOS but on Android it is on the left side then if we move to the adder to the page so this back button this is this icon is different on Android and this is different on iPhone and then again the same heading it is different it is in the center on the iPhone and left align in the on this Android okay so this is the main added trip screen from here we can create a new trip so first we have these categories so these are the predefined categories if you don't find your category you can use this other category for me let's use this island here so the data we are storing using sqlite database right now it does not have any server so these two environment these are not going to be in sync we need to add the data separately for these but if I got good response on this app on this video so I'm definitely going to create an API and maybe we can create an web interface also using Blazer webassembly hopefully if I got good response on this then only I'll do that else we'll simply live with this only okay so title let's say anything many time location some Island we can give it whatever name we want and then we can set the trip uh date from where we are going uh and start date and end it basically then we have the strip status so we can manage expenses for our the completed trip Zone also so the trips we already completed for those also we can manage expenses so this is planned because this is in future we can save this trip and now we can see the strip on this home page now let's see we have these menu bars on this trips page we can see the list of all the trips with the name the status location and the dates and we have this plus icon on the top using which we can create a new trip go back then we have this third menu item that is again going to uh to the add a trip page go back then we have this settings page on settings we can see this so my profile change password manage expense categories which I am going to show you in a bit and we have this sign out button so when we press sign out it is going to sign us out and then we can again sign in if we press if we enter the wrong password it is going to give us this nice alert for the wrong password sign in and now we are here okay now this is the detail page of this uh trip so we can see all the stats then we have this added button if you want to edit the trip we are here and we can modify anything so let's say if we started the trip we can set it to ongoing we can save it and now we can see the status is ongoing okay now for this trip we have not added any expense so it shows this you haven't added any expense we can add a expense using this button plus add expense or plus add expense here you see this 0.00 this is the because the expense is zero right now let's add a new exponent so it navigates us to this add expense phase here we can add any expense let's say petrol we added petrol choose category so this is going to in the fuel when let's say 30th only done and add expense expensive this is the nice toast message now we can see the single expense list here so this expense we just added and this is the total amount right now let's add one more add forward let's say we had some breakfast and it cost us let's say 17 dollar and then this will go to food category when let's say 31 first add expense now we can see there are two expenses petrol which comes under fuel then breakfast which comes under food these are the separate uh costing and then this is the total expense for this trip we can see if we want to add it some expense we can definitely tap on that and then we'll be here and we can simply modify it let's say it was not 17 it was 17.45 so we can edit this as expense and then this is going to be updated all this data is being saved in the sqlite database so if we close the app and come again then it we can see this data okay let's go back and this time let's create one more trip for this time let's say we are going to Mountains for some Adventure with some adventure group okay some mountains area from you know let's say we are planning it well let's say we we already had the strip so it was from 1st of August to let's say six October and this is already completed not canceled it is completely up we can create a trip then we can set it canceled as well because sometimes it also happens so the cancels fourth canceled also we can manage the expenses for example we added some shopping we bought some tickets and all those so if we cancel the trip then also we actually spent some money on that so we can manage those expenses as well now we have these two things here now we can go here there are no expenses for this one go back but we can see expenses for this one right and then the strips we can see these things cool so everything looks fine then we can come here then this manage expense categories right so these are the expense categories we have right now so I have added these predefined categories in the sqlite database already so we will ship these categories if you want to add another category you can simply tap on this plus icon and you can create a new category for example let's say what else is there some let's say some medical expenses we can save it and it is going to be added here now we'll go to some prep and we will add some expense then if we check the category we can see this medical this new category here so this is the app we are building and this is how it looks on iPhone let's see it in Android so let's do the same thing we will add a trip and we'll let's do the same thing so this me time this was Island this one me time location some Island trip from some date we can have any date set and let's have it planned only so save trip trip saved now we can go here and we can add our expenses forward let's do same thing but in reverse order so we'll have well let's say we first we had our lunch which cost us some weight around 24 category it was food when it was 26 let's say 26 had expense now we can see this expense let's add one more this time we can say let's say tickets and we okay I need to remove this this is the validation summary which I added to check I need to clean this up so let's say we visited some zoo and we bought some tickets there amount let's say 10 dollars the category it will come entertainment I guess then the date we can set and then add expense now we can see these two expenses and if you want to modify it we can simply go and modify anything so let's say 10.5 this time category is fine edit expense and now we can see 34.5 dollar and we can see these things changed here we can add the trip if you want let's say this is not planned now this is ongoing so we can save this trip and we can see this ongoing now go back all trips we can see the old trips here we can create a trip from here as well then we have this plus icon from here also we can create a trip then the same settings we change password we can change the password manage expense categories similar thing we'll see here we can create a new category which will be populated in the express screen okay and then we have the sign out so using sign out user is going to be kicked out from the app and then you can simply sign in again so this is the app we are going to build using.net Maui Blazer hybrid with some native Maui interrupts at services for example we will check if we are on Android or iPhone we will use equali database then we'll have these different icons then we'll have different uh toast messages alert uh prompts and all this kind of amazing stuff we are going to do in this video okay so before continuing let's smash that like button if you like this overall design and and let's continue all right so I'm here in vs4 Mac so I have created a new dotnet Maui Blazer hybrid app and what I have changed in this I have copied this box icons CSS and fonts to this triple W root folder and I have added these couple of images to this images folder and all these images I got these images from box icons the icons the Box icons I get from box icons and those images I got those from flat icon this flat icon.com from here you can search let's say uh Hills if you search you can get these Hills and all these so this I am using this I particular icon you can simply download this and use this then I think I used one or two images from this pixabay.com so you can check out this I'm going to drop Links of all these in my description box so you can get your own icons and images from here for CSS as I already mentioned the icons I'm going to use box icons then this CSS this font I am using this Poppins font so this I got from Google fonts so you can simply get this from Google fonts post.google.com then you can search for Poppins here this for Pins font so I'm using this font all right apart from this what I have done in this index.html page in triple W root folder in index.html I added this box icon CSS like this and then I made this change to tripex this the name of the application this is tripex apart from this uh in CSS app.css I comment out this thing so this was the default icons Library this project template uses so I commented this out this import URL open ionic open iconic and this bootstrap.min.css then I commented out this HTML body as well because it was using this this default font I added this at the red font face font family this pop-ins which I added to this folder and then in for HTML and body I am simply changing the default font to Poppins and then it will be fall back to the other fonts which were already there after this I comment out these things a BTN link so I am simply removing the default Styles which we are not going to use in our app apart from this for this valid and invalid modifiers it was using this outline so it is not aligning with our approach our text boxes we are going to use rounded corners but this outline this uses the we could say the square rectangular border so that this will look very bad that's why I simply change this outline to border color and I am using the same color 4 invalid as well after this I have added couple of helper classes here so for font size I have added this 11 12 13 14 these font size is font size 12 px11 PX after this I am using these three uh utility classes for width so VW viewport width 95 so I'm setting width 95 VW then 450 and 490 so we are going to use these inner app cool so that's all I have done so far so let's see how this app looks like I'm running it on Android simulator so the uh the hot reload for Blazer oh it is on Mac sorry build canceled iPhone 11 like this yeah so the hot reload for dotted my blazer hybrid it does not work most of the time so sometimes it works but most of the time it does not work I try it with Android emulator iPhone simulator and my Android device as well I have Android phone so I tried that as well so sometimes it work but most of the time it does not work so we are going to have a hard time for this so we will be keep on redeploying the app throughout our building okay till the app is loading okay app is here so you can see this is the default layout which does not have anything right now okay it had something for this content and all this but I removed this but you can see the font has changed so this is the thing now we'll start working on our app so first thing we are going to have couple of models and in this we were going to use equal light so for that also we'll see in a bit initially first thing let's create the models which we need first are not models first we'll create couple of folders so first let's create a new folder for our models then we'll create a new folder for our services and then let's create a folder for utilities utilities fine in models we are going to have two types of models one database models so for those I am creating a new folder in models you could say these as entities as well and we can have these models in data folder as well but how maybe let's have this in data only okay let's remove this data base folder from here delete delete and inside this data folder we will have our all our database models so let's create our first model class empty class we'll call it user so our app it is going to run on Android and iOS so there will only be one user but still we want to have that user because we are using sqlite to store the name password and all those things so for that let's start adding properties first we will have an integer ID after that we'll have name then we will have username so the first name is actual user actual name and the second is login username basically then we'll have a password [Music] okay this is user class after that let's have trip this is going to be a class in this we are going to save the trips the travel trip basically so in this we'll have paint ID which is trip ID then we'll have title or heading trip title basically t i t l e title after this we will have location we are using free text here after location we'll have an image for this that category image if you remember I showed you earlier so string category image category image after this we will have the date range and we will have this nullable so from date to date to date fine after this we can have audit field so we'll say added on when this trip was added to the database and we can have modified on as well date time modified on okay after this if you remember we had the trip status so for this we'll have an enum so public a m and we'll call it trip status and in this we are going to have our statuses first we lose plan let's use zero then ongoing after this we can have completed and then we can have one more canceled canceled let's say minus one like this fine now we'll use the strip status here just status only okay save everything we are good now now next thing let's create expense because after adding the trip we are going to add expense so public class expense first thing we are going to have ID so I'm taking it long after that we'll have a string or maybe before that let's have integer trip ID to map it with that trip after that we'll have one string which will tell us for what is string [Music] for what we added this expense after that we will have amount before date we can have decimal amount or we can have double amount after that we are going to have a category put this expense so this is expense category and after that we can have a date time and this also we are going to have in the label we'll say spent on when did we made that expense basically cool and after this we need to have one more uh one more model and that is going to be for this expense category for this we'll have public class expense category because we are going to store this category in the database and we are going to allow user to add new expense categories as well in this we will have only single column in this table single property in this model which is going to be name after this we are going to have one more if you remember this trip this category image so we need to have these category images so for this what we'll do we'll create one more model here which we'll say let's say public class location category let's call it location category only and in this we are going to have two things first string category name then second is going to be category image like this so we have created all our models first thing now we will move these these models to separate files so let me quickly do this move type to this move type move type by the way I'm getting used to bank so I found this shortcut commands so do let me in the comment if you are using vs4 Mac or you are using visual studio on Windows cool so I have copy I have moved these files to separate all these class models to separate files after this next thing we are going to implement uninstall sqlite database so for this if you go to my YouTube channel YouTube okay I'm not logged in in this youtube.com Prince um it should open up my YouTube channel right like this on my channel you can find the I have created two videos this one view full playlist so how to create sqlite database how to connect this so everything I have already made this two part Series where we implemented sqlite database models validations so many things we have done in those videos I would recommend you guys to check out these two videos so that you will have better understanding how sqlite Works how to implement it how to integrate it with dotted Maui so I'm going to drop the link of this playlist in the description box so please do check this out we are going to use learnings from these videos in the current video in today's video so for this and the code for this this will be on my GitHub so this mouse equally in this we are going to use things from here so first to implement sqlite we need to install some packages and those packages are going to be these two packages sqlite net PCL and sqlite PCL row dot bundle green these two packages so we have to approach this either we can simply copy the name and copy the name go here right click and manage new get packages click on this browse and then search we can search for it and we will get this project this uh package then we'll simply say add package and it is going to be installed in our project or we can directly copy these two lines and add these two lines to one CS approach trip action expense manager CS Pro so if you are on Visual Studio on Windows if you'll click on the project directly it will open the Cs project you can add these there and if you are on the Mac you can right click on this Ctrl click and then you can say edit project file here at the very bottom maybe you can see we have added this project this package so it is here so you can simply paste both of these here and after that when you will build this project it is going to install these packages to our project so we can simply say rebuild and it is going to install these packages middle failed that is fine we'll fix this okay we are not going to be on Mac this is fine cool so we have added the packages now let me build it again rebuild restoring package and everything is fine now we have added this after this in that Mouse equal light only I guess in data folder we had this database context this file I have created this helper file this is going to be uh we could say a single point from where we can connect two sqlite database so I'm going to Simply copy this first let's make let me copy the names database context in this data folder only we'll create a new file new class basically database context we'll call it database context only create and then again go to this and let me copy this database context directly complete file copy and just paste this here like this fine so what it has let me add these usings using sqlite and we are good expression using system dot link dot expression and we are good so we have this file what it does initially we have this database name so for our case we are going to say trip packs manager.db3 after this we have this private sequolite connection underscore connection then we have this database property private property so we are using lazy loading and cached instance of this equilight connection with these flags equally open Flags dot create read write and shared cache and now we are going to use this database object this is private then we have couple of uh helper methods these are private methods and then we'll have this public method so how these are going to be used we can simply create instance of this database context and then we can get all async it is going to return the list of all the items in a table then we have get filtered AC we can apply wear condition we have this execute this is private so let's skip this so I explained this detail in that video so you can I will recommend you to definitely check out those videos to understand these things better then we have this get item by key async so we can pass the primary key and it will going to give us the object from the table then for adding we have add item async update item async delete item async delete item by key if we have key then this dispose this is the dispose method which is going to dispose this connection when this database contact this class goes out of the context fine okay we have this class first thing we need to register this class in r Maui program so we'll go to our Maui program in here we can have separate method so we'll say private void and let's say add services and we will get this I service collection services and then we'll simply register add a Singleton this database context class like this and then we'll call this add Services method so this is going to private static void ad services uh you could have this as an extension method which you can have somewhere on the services but right now I'm having this here only from here we'll call this ad services and we'll pass Builder dot Services now we are going to have all our service registrations inside this only this will clean it up later but for now let's have it like this okay everything is fine we installed sqlite packages we added this database context class after this let's go to our models and our on our models we'll add some cycle light attributes so first this ID this needs to be primary key and this will come from sqlite using whatever this was in this sqlite okay let me first save everything like this okay now let's say using SQL idea I paste this issue as well so for this particular thing sometimes the intelligence does not work sometime it shows uh red lines for errors but there were no error everything was fine but still it shows those errors so let's use for those cases I had to close Visual Studio vs4 Mac and then open it again using sqlite we are going to have primary key and then there is one more attribute which is auto increment so it is going to use uh disorder increment so it is going to automatically increment the value whenever we are inserting a new user so save after this let's go to other uh other models for expense will have the same thing we'll have first primary key primary key using sqlite and same Auto increment like this trip ID is fine 4 is fine but four we are going to use data annotation validation so let's add these and I'm not going to use separate models for this for expense we'll use same for database model and then same for our view model so let's add required validation for this so required we'll use system component model data annotations after that we will have this max length and for this let's have a max length of 100. and now we will have a problem here max length is defined in sqlite as well as this component model data annotations so we need this max length from sqlite for sure because we are going to use that in uh in our what we say for a database model but if we add it from data annotations then it will be validated first on the screen only so we are going to have this max length from this component model so for this what we can do we can use aliasis so we'll say max length attribute equals and this should come from system dot this component model dot data annotations dot max length attribute like this now this max length is coming from this aliased using fine after this amount is fine category also we can have a max length or we can skip this because we are going to display the category in a drop down so it will be from there only so we can skip this but we need required for sure because we want user to select the category then for this amount we are going to have some amount so we can set our range attribute here which will say 0.1 this should be the minimum value and maximum value we can have double dot Max value so whatever double can take categories fine this is fine this is fine everything looks fine now right and for trip as well we can have if we somehow missed this all uh we are not going to get it from user so we will be good okay now let me copy this max length because we are going to use this on other models as well so let's go to expense category so in this expense category we have only one property which is this name so we'll use this name as primary key primary key from sqlite and we'll use the max length here and maybe 100 again on this as well save expense category this is fine now let's go to location category so this is the image here we will use this name as primary key primary key light okay okay and then we can have in the so we can skip this because location category we are not giving user uh some screen where user can add these we are going to give these location categories hard-coded as a seed data for our sqli database we are going to give this so we are good we don't need to provide other validations but it's always better to add the annotations and validations you can have that max length required on these cool now we are on trip so let's add the attributes here first this trip ID this is going to be primary key from sqlite Auto increment from sqlite then this title so for title we will use max length first we'll use required required from component model then we'll use max length for this title let's have a max length of somewhere 30. then this location this is also required and max length we will have some what let's say this also 30 or maybe 50. after that this category image this is also required and we'll use max length we don't need to have these attributes attribute word actually we can skip this max length and let's have 30 only for category image then we have from date to date added on and these date property so we are good with this for this trip status let's have a default value of tripstatus dot plant this is going to be the default value cool trip status this is enum so we are good then comes user we already added so we added the annotations to all these let's continue now next thing we need to have some seed data initial data for our app so the category location category image is basically and then expense categories these two things we are going to ship in our app only so for this in a Services folder let's create a new class and we'll call it C data service like this create and we are going to inject our database context class database context using this let's call it context field contact field like this and in this we are going to have one method public async task we'll say see data async like this okay now first we need to have our category so let's say expense categories we will have a new list of spring and let's have categories so first food fuel entertainment entertainment this food fuel entertainment shopping and let's have others we will allow user to add more categories so user can add these categories later then we are going to have are those location category images so let's say location categories this is going to be a new list of location category like this and we are going to have location categories new location category and let's do one thing let's go to this class and let's add a Constructor here generate Constructor for both of these name and image let's have default Constructor as well so this Constructor this parameter Constructor we are going to use this and this is going to be default which anyone can use framework and use Library can use so this location get this one we are going to use for our R is so instead of adding these like this we will say new location category then name of the category and then image URL of the category so we have images in our images folder inside triple W root so in Blazer triple W root this folder we can access directly from any page from any razor page soft this is the default then we have slash images so it will go to this folder and then we have all these images so for Beach we have a we are going to use chair.png this image for Beach chair dot PNG these I got from box icons like this now let me add other as well I have added all these location categories so category name and then image which I already added is into this images folder and I have this collection now now let's add these location categories and expense categories to our database for this what we are going to do we have two approaches in our database context we have add item async okay we have add item async only we can have one more method to insert multiple items at once but as we have this single method so we are going to use this only but it's up to you can simply create a new method to add multiple items at once here we'll say where location in location categories like this and then we'll say a weight context dot add item async and we can pass this location like this if we want we can explicitly set the type but because the item was of this type so it is going to use this maybe I should make the text a bit smaller because it breaks at wrong place tax regular we have this 12 let's say 10. okay it should be visible I guess okay okay so we have added these locations now let's do the same thing pose expense categories expense categories so we can say expense category in expense categories here we'll say expense category and then we can set expense category like this and it is giving us some error and which is because of it is of type string it should be of type expense category so if you go to expense category let's do the same here as well we'll add Constructors here so generate Constructor with this name and then we'll have a default Constructor as well so expense category go back to the file and instead of these direct names we can use this approach new this thing this thing I'm simply using the default Constructor like this like this and let's change this string to expense category like this now we have expense categories and it is not giving any error so we are good now fine everything looks fine now let's register the C data service so let's go to Maui program and after this add Singleton database context let's add one more and we are going to use this C data service as transient say data service like this and now we are good now we need the C data service to run at the very beginning so for that in our app we have this app dot Dremel and app.zml.cs this file this class so this is the main entry point of our.net Maui application so from here we will call that see data survey first we will inject that see data service let's do one thing let's create a global usings file so we can get rid of all these usings at once so in this project I am going to create a new class I will call it Global usings create remove everything and I'll say Global using and trip expense manager first this then Global using trip expense manager dot data and let me copy it a couple of times and then dot data services Dot model shared okay when we'll add our model then we'll add models as well but for now let's have these three only fine and let's add these two are imports.racer as well so if you are familiar with blazer we are going to have Pages razor components razor pages in Blazer so on those we will need to inject these Services models and all these things so for that we can have this underscore imports.racer we can add those usings here so it will be available automatically to all the razor pages like this so Global usings is for C sharp files and this underscore imports.razer this file is for all dot razor extension files so razor components Blazer components this is global usings for those save everything let's go back to app.zml.cs and now here we'll say see data service like this see data service will have a private read-only field here underscore C data service like this and now on this app we can override a method and that is going to be on start this one so protected override wired on start so whenever app starts then this method is going to be called so from this maybe after this we can say underscore see data service dot seed data async like this now this is an async method so we need to have await and because this is an event we can have a Sync here protected override void on start and from here we are calling this now this will work but there is one issue here and the issue is this on start this is going to be executed always uh whenever a app is starting first time right when we start this this will run and when we did we use the app we close the app and tomorrow when I when we again come back to the app then again this method is going to be called and the seed data is seeing this method is going to be called and it will simply get these expense categories location categories and it will add these items again so we will have duplicate items this is not what we want right so for this what we can do first we will check if we have this data already if we seeded the data already so for this what we can do before doing all these we can check if we have this let's say this first categories food category in our database so what we'll say we'll say let's say food category equals a weight we have context then we can say get item by key async and we can pass the key like this get item by key async okay we need to tell what is the table type so this is expense category like this and then we can check if food category is not null or let's say if this is null we know we already seeded the data so we can simply return from here data said already say d dot data setting is done already something like this now there is one problem this get item by casing this throws an exception if the key does not exist so for this we need to use one method which does not true if the item does not exist so for this where is this get item by casing right so we will let's have one helper method here public async task of T table the type of table and here from here we can use find async T table and here we can have the key which will be object primary key and from here we can directly return database [Music] database dot find async and from this find async we can pass the primary key like this we just need to tell the type which is going to be this T table now it is the issue return the object the T table must be a known abstract type so we need to have this constraint so where T table this and it has a default Constructor so this and this is an available method like this so we are going to use this find async method here thank you or maybe let's use the same approach we had for this right this execute one okay let's copy this and use this approach like this execute a weight and this is going to be this line cut like this so what additional thing this thing does return a weight we don't need to have return here missing a fade like this database dot find async Movie Database now what is the issue is this um yeah it should work oh this is not T table boon this is T table only fine so this execute function this is in helper method here which is execute async it creates a table if the table does not exist already so it creates the table then it will query it so we need this thing so I explained this in the video where I explained secular interaction then you can check those that video out cool so we have this thing here now we'll use this find async method so if someone from you want to modify that existing repo you could add this method there or maybe I I'll add it there no problem fine so here instead of this get item by key async we would use find async like this now if this food category exists already we will have this SNL and we will return it from here if this does not exist we will no is not null it should be normal right if it is null that means this does not exist and then we will have these Collections and then we'll simply add these collections to the database so everything looks fine let's add couple of breakpoints and see how these things are working let's run and we have an error here let's see what is it and type a name in space Android so this thing remove this and let's rerun building app is loading okay it is taking time maybe because we made so many changes oh it is here at this seat data I think fine let's try to move step by step so food category and now if we see food categories null because we are running it for the first time we don't have this food category here now if we continue it is going to add all this data run we are here now let's stop this and run again this time we already have data in our database sqlite database so the check this check actually should give us a not null value okay app is coming hmm okay it is here let's run this time food category we can see the data so we have this data in our database so this makes it's certain that we this data got inserted now if we continue it will come to this return and it will pass from here so we have the data already in the database so see data is working cool now we'll start the actual working so let's go to the first Razer page first let let me remove this breakpoint fine let me remove this now we will come to the pages and we'll create a new page here but the first page this index.ery this is going to be the first page in our application which uh gets shown to the UI for the first time when we open the app this is the first page so we'll have some logic here but before that let let's clean the project up it has all the data the which we are not using which comes with the default templates so this weather forecast service we don't need this weather forecast service and this weather forecast model so let's delete these delete and delete this fine after this we have this counter dot Razer and fetchdata.razer these two pages so let's remove these delete counter dot razor delete fetch data appraiser delete after this in our shared folder we will have nav menu and Survey prompt so let's delete these two as well delete and Survey prompt Also let's delete this cool then this main layout it has this some things for now let's remove everything will add the markup later and then we have this main layout.tracer.css so we don't need this complete CSS file so let's remove everything from the CSS file after this let's go to Maui program dot CS file here we had this registration so let's remove this now we have cleaned everything up let's remove these usings we don't need this now okay looks like everything is fine now let's try to run it so that we can see that we didn't break anything we only removed the things which we do not want foreign black screen no there's something and now we had this white screen for some time then it got removed right so we'll work on this but for now this hello world this is coming from our Pages index.tracer this hello world okay now we can remove this as well save so everything looks fine now let's see if this is working the hot reload yellow world looks like this is not working okay not working okay so we need to live without it only we will keep on refreshing this okay so this is the first page which is going to be shown to the user now what we'll do here will create other Pages first let's create a new pages then asp.net core razor component and we'll call our page sign in page okay and then let's add the page route to this which will be at the rate page and we'll say sign in sign in like this let's use sign in then create one more file razor component and we'll say sign up sign up page like this and the URL we are going to use is you guessed it right sign up cool save everything now on this index.rezer page let's remove this H1 hello world we don't need anything we will simply have a code block here in this code block we will have some logic and that logic is going to be inside this override on initialized async method protected override task on initialized async fine so the logic is going to be we will check if user is already logged into our app we will pass the user directly to the home page and if user is not logged in then we will pass the user to the sign in face that is what we are going to do for this let's first sign in we have this sign in sign up let's have heading sign up let's create one more page and we'll call this home page home page like this and home page like this home page and let's have the URL route as page and home save everything fine let's have that logic so the logic where should we store the that status that if the user is logged into our app or not so any guesses you can pause the video and drop me a comment where you'll say that where should we store that uh the data that if the user is logged in or not where should we store that status in our app so because this is just in status and we are on a dotted my mobile application so an Android and iOS we have shared preferences which we call preferences so we have preferences API we are going to use that preferences API to store the status of our user and for that instead of directly checking that thing here what we'll do we'll create a service so in our services folder we have C data service and now we are going to create a new service which will be a class let me stop it first okay that is going to be let's call it auth service stop and now we should be good fine in auth service we need to check if user is already logged in if not we uh we will have a method here so public Bool is logged in or signed in it's signed in maybe we can have this as a property like this when here we need to check preferences so we already have this preferences so it's better to have it as a private read-only field layer private read only I preferences underscore preferences preferences and then we can have initial value to it preferences dot default you can register it in the dependency container on Maui program and from there also you can use it if you want but for now I'm okay with this so preferences Dot we can say contains key if we have some key and that key is going to be let's say logged in if we contains this key preferences has this key then we will be certain that the user is signed in so we are going to use this key when we will update this so let's have public void sign in we will provide other values sometimes later but for now I just want to show you how we are going to set it so after signing in so checking the user credentials from the database checking the user credits from database after that if everything is fine then we will set preferences Dot set and then we'll set this key so logged in and some value we are not using this value right now we might use it later but for now we should be good so this thing and now we will have one more method for sign out so we'll add actual logic later but for now let's have it like this so we'll say preferences dot remove and we can have this key now we are repeating this hard-coded string again and again so it's better to have it as a constant so we'll say private const string we'll say logged in key and then we can have this thing here like this and then we can use this key at all these places like this we'll add actual logic later don't worry about these things we'll see these in detail now we have this it's signed in property we can use this on our index.tracer page fine let me save everything first now we'll use that or service here so for that first thing we need to register our auth service so we'll come here we'll say Services dot add we can register this as transient only uh service now we can use this auth service owner index page so where is your index page index.tracer here we can inject auth service and we'll call it auth only and in this phone initialized async this is not an async method right this this is simply simply property so we don't need this async method we can use the other method which is on initialized only this okay now we can remove this we don't need this thing here we will check if auth dot it signed in if user is signed in else user is not signed in so if user is signed in what we'll do we will navigate user to the home page this page if user is not signed in we will move navigate user to the sign in page in order to move from one page to another in Blazer using uh C sharp we can have navigation manager so we will inject navigation manager this is a class provided by Blazer let's call it navigation and on this we can have navigation our property okay let's call it navigation manager only so it is we can name it whatever we want this this is a kind of property injection so we can name it uh whatever we want and then we can use it here on navigation manager we have a navigate to method in this we can pass the URL where we want user to be navigated so in this case we want this to be on home page and then let's copy this paste it in elf and this time we will say sign in so this is on the sign in page if user is signed in it will go to home page if user is not signed in it will go to sign in page so this is what we will have this on this Logic on index.tracer then this URL these URLs this slash home slash sign in these are coming from these Pages only so this first line this page and then this is the actual page URL for this particular uh component laser page cool after this one thing when we navigate to some page in Blazer and if we press back button it comes to the previous screen right now we have this index page and from here let's say user is not signed in so this condition will match it will go to sign in page when we got on this page if we press back button it will automatically redirect back to this index.tracer page and from this index.rezer we have this logic in on initialized it will automatically trigger and it will check it again and it will redirect user back to the sign in page so there is going to be some Loop that is not what we want so this index page we want this purely for this logic we don't want to user come back to this page somehow we need to remove this page from this navigation hierarchy so for that on this navigate 2 method we have other parameters as well so we have this Force load which is for reloading the page Force load so how this navigation manager works it uses Blazer routing so it is not going to refresh the complete page but if we set this Force load true it will refresh the complete page this is what we want not what we want then we have one more which is replace this replaced so this is we are going to set it true this means we are navigating to this URL and we are replacing the history state that means we are replacing the current URL with the slash home URL that means there is no previous URL so if we will go to the sign in page or home page we'll do same for home page as well and this so when we are on sign in page when we will press back button there is nothing on the back so user will automatically come out of the app so user will be kicked out from the app because there is no previous page so this page does not exist in the navigation stack navigation history cool let's run this and see this time it should directly go to sign in page let's remove this breakpoint let's open this and user should it should automatically open the sign in page because user is not signed in very successful waiting for the debugger to connect to the io simulator okay I've been installing Now app is loading my Mac is very slow today so maybe I can somehow clean it up if you guys know how can I clean some junk or cash so do let me know in the comments so that I can Implement that and I can clean my Mac this is behaving very strange so very slow actually from I think today only or maybe day yesterday okay so user is on sign and we are on sign in page sign in page because the user was not signing so this thing worked fine cool we are good with this next thing we will work on our sign in page so for sign in and sign up let's create models first so in our models folder I am going to create new class find in model and let's make it okay let's add property so first we will have a username and then second we'll have password and we are using we are going to use data annotations for this so required and max length let's say 20 and let's copy the same validation for password as well after this we'll have one more model for sign up so sign up model where first we'll have name and then this username and password like this and this is again going to be required and max length let's say 30. and move this method this sign up model to it's separate file cool so we have the sign in and sign up models after this let's go to auth service and Implement actual sign in and sign up methods so for sign in we will get a sign in model okay so but before that let me add the usings so Global using trip expense manager dot models and let me copy this using we will use this same using in underscore Imports so that we can use it on our razor pages okay now auth service sign in model now from this model we'll create our user object which is our database entity new user so username and this is sign in right no we need to do this for sign up okay first let's create sign up then we'll Implement sign in so public async task sign up let me sync sign up model from here we'll create our user first name equals model dot name username model dot username and password model dot password like this now we need to add this user to our database so for that we can say await now we need our database context here so let's inject this database context context create a field underscore context underscore context and then we can say underscore context Dot add item using the type of item is going to be user and this user object like this now this it's saved but it returns Boolean value so if we go to its implementation we can say it returns Boolean value so true means the record inserted successfully um okay so from here we can return uh let's create a model inner models we'll create a new file so we need a different type of result from all these method calls so we'll call it method result and we'll create it as a public read-only record struct method result method result and we'll use Bool is success and a nullable string for errors so we'll use this type so this will return this thing like this baby and let's add some Factory methods to it so we'll say public static method result we'll say success and from here we'll simply return new its success is true and error is null in this case then we'll have one more static Factory methods so public static method result let's say fail fail and we'll get error object or error string in this and from here we can return new false so its success is false and the error message is the error message we got from the consumer from the client sorry so now we can use these methods directly here so what will do here we will simply add a if condition if this was true that means this operation was successful so we can result return method result dot success like this if this was not the case we can simply say method result dot fail and right now we don't have any error message we can show our own error message from the consumer from the razor page and we can wrap this in try catch as well and then we can use this methodical fills this error to the that exception message but right now we are good with sign up basing this only cool now when user was signed up after this we will navigate we will redirect user to the home page and we will set is logged into true like this now sign in so this is also going to be async task method result sign in async this is going to be sign in model fine here we will first get this object from the database so we'll say DB user equals context dot I'm using this get filtered async but you can try other methods as well I'm using this one so get filtered I think we can pass an expression to this the expression I am going to pass user U dot username equals model dot username and U dot password equals model dot password let's say users and here I'll say where user equals users DOT first or default users okay we need to await it and then we can say first or default now we will check if user is not null that means this username and password is correct and we have this user in the database so if this is the case we can do this preference setting and then we can return method result dot success if that's not the case we need to return error so we'll say return method result dot fail and here we can say incorrect credentials and you if you want to more fine grain it then you can simply first check with the username if username exists and password is not matching then you can say incorrect password and if username does not match then you can simply return that user does not exist but for now for our case this is fine after this we have sign out method in sign out we are simply removing this key so that is fine I guess yeah this is fine now let's move this preference dot set to a separate method because we'll use it for something else as well down the line so for now let's move it so we'll say private or let's do one thing instead of setting this true let's set the actual user because we need are going to need it on the settings screen there we need username okay so for this first let's go to models and in models we'll create a new class or let's say a record logged in user and here we'll have ID and name at least these two things and let make it straight read-only struct fine let's move it to separate file and now we can use it in our auth service okay here we'll say private void let's say site user and we'll get a user object and then we'll use this thing here we will first generate logged in user object logged in user equals we'll say new logged in user and we'll get user.id and user.name like this and then we are going to set this logged in user here in Json format so for this we can say or let's add this method on logged in user only so we'll go to login user and we'll add a method here public string to Json like this instance method and here we can say let's remove this thing Json serializer from system.txt.json Json serializer Dot serialize and we are going to serialize this object only so here we can say logged in user dot to Json now we are good with this and now we'll call this set user from both of these methods so sign in async will say set user we have user object and in here in sign up method we'll call sat user and here as well we have this user object so I guess this auth service is done cool now let's go to our sign in page in Pages folder sign in page now we'll start working on this page first thing we will have our model which is sign in model for this like this now we'll use this design and here we'll start working on our HTML so first everything should be wrapped inside edit form edit form and we cannot see this because it comes from from where it comes so still no not system Microsoft dot asp.net course.com components dots forms dot edit form is this correct Microsoft asp.net core components forms okay let's check this thing on C sharp page I'm just checking this namespace forms dot edit formula this is correct okay let's add this Microsoft asp.net core components.com honor imports.razer so this is already there Maxwell Express core components forms focus it should have worked okay this is the thing I was mentioning before that sometimes it this dotnet Maui Blazers uh in vs format this is not able to figure out that is this the correct element correct control or not and I'm not sure if this is the same for Blazer as well the Blazer web assembly and Blazer server so do let me know in the comment if you guys tried this one Mac I have never implemented any Blazer application on vs4 Mac this is the first time I'm doing but this is with the dotted my blazer hybrid so maybe it is for Blazer hybrid or it is same for Blazer as well Blazer web assembling server do let me know in the comments okay we'll say this underscore model for this edit form and in this edit form now we will start designing our HTML so first we will make it as a card to div class card and on this underscore model after this let's add data annotations validator and notations validator okay and this dim class card let's add H1 right now save everything I just need to check if everything is working so I'm running it let's see okay app is coming up sign in signing so this okay that means this thing is working okay we can start oh maybe let me try closing the visual studio and then open it again so that these errors go away let me try this I closed it and opened it again and now the errors are gone this means everything is fine now okay so in this Border in this card I'll add a border class as well so I will say border 0 I don't want any border then I need a shadow so we'll say shadow SM Ile shadow and after this we'll start working on this card body so all these classes card border zero Shadow SM card body all these classes are coming from bootstrap so we are using bootstrap in this then we'll say text Center and in this let's have an H4 and we'll say welcome back and after this we'll have a small helper text with the text muted class so it uh Fades the color of this tag so it will be in some slightly grayish color so here we'll say sign in to your trip packs account like this okay after this p now we'll use Dave class v stack this is the vertical stack we have text Center on the parent right so let's have text start on this we will start this from the left side now we'll have our form components so mb3 margin bottom three will have a label with class form label this is going to be username and after this we'll have input text with bind value and this should be model dot username we are binding this input text value so this is two-way binding with username so if username changes the input text will have the updated value and if we change manually it in this input text this text box the model.username value is going to be changed fine after this we will have a placeholder place folder let's say enter username and after this we will add couple of bootstrap classes so first form control so after that we will make the corners rounded completely rounded surrounded pill and then we'll have a smaller font size fx6 and that's all what we need here then we'll have a validation message this is for if there is any error in the validation so we had the required and max length so if it fails to validate on those attributes then it will display this validation message so here we need to pass a 4 and this is going to be model dot username like this and now we can copy this one more time for password so this time we'll say password underscore model dot password enter password placeholder password and for validation message as well underscore model dot password and we'll set one more thing here on this input test because this is password we'll set type attribute to password fine after this we'll have a submit button so we'll say button type submit and the button text which is sign in and on this button as well we'll add couple of classes and the classes are going to be BTN BTN primary and the same rounded pin so we are going to use this rounded pill Class A lot inner app so let's run it and let's see how it looks okay it is coming pretty good welcome back username password sign in and the shadow so everything looks fine cool now let's move this section to the center of the screen and let's have that application name that is tripex and that image which works as logo for our case okay so for this before this added form let's add a wrapper we'll say div class we'll add couple of classes here and we'll wrap this added form into the div and the classes we are going to have first we need complete height so vh100 that is viewport height 100 so 100 of the viewport height after that 100 VW so that means hundred percent of the viewport width then we'll have some padding so P3 all these classes are coming from bootstrap after this let me move it okay now we'll have display Flex here we'll have Flex direction as column so that we can stack the items up and then justify content Center and align items Center so we are centering the items vertically and horizontally both align items Center all these classes are coming from bootstrap in this we will first have a div foreign first we will have one image and that image is going to be from our images then we have one image which is travel and tourism travel and tourism dot PNG this image okay let's have alt tag we can skip this if this is not required but it is a good practice to use alt tag for IMG tags alt attribute with IMG tags after this we'll have H3 with class we'll have let's say margin 2 or margin here margin two is fine now name of the app which is tripex in this case save and it did not pick up let me restart the app hopefully Microsoft fixes this hot reload issue with DOT net Maui Blazer hybrid in maybe.net I don't know it is coming up let's see how it looks okay fine we can see something what is this x oh this might be the tripex okay now let's set heightened width for this image so on this IMG we are going to add classes uh let's say Max Auto if this works to move this to Center let's have logo and here we'll use a style tag style type text CSS text CSS and we'll make it scoped so that it applies only for this page and here we'll say logo and we'll set heightened with 100ps so height 100 PX and width 100px save and rerun so this is how it looks this is coming a pretty good actually tripex I missed e very trip Acts save fine now next thing let's change the background color to the gray color we are using for our app so for that what we can do we can go to the triple W root CSS and mainapp.css in here we have this HTML body font family Poppins here only we will set background color background color so we are setting it for our entire app and here we'll use a variable and this variable will come from bootstrap so we have BS Gray 200 so this color is defined in bootstrap so this is a lighter version of gray color save everything rerun okay now we can see this okay cool it looks great now inner sign in page we are going to use the same layout for our sign up page as well right so what we should do this image this background color this heading all this is going to be same for sign up page as well so for that we should move this to upward in a layout so that we can use that same layout for both of these pages so for this what we'll do we will go to a shared and we'll create a new file here this is going to be asp.net core razor component and we can say let's say auth layout auth layout and in this we can simply copy this upper code like this and this div after this we can have one more div let's have some margin and white 3 from top and bottom and here we'll set our body so because this is a layout it should implement or it should inherit from inhabits layout component base and this we can check on the main layout so this line layout component base let's add it here so inherit from layout component base and then we can use at the red body so here our page is going to be rendered and now we can get this style out of our sign in page and add this on this layout so we can have style here or we can simply create a new file auth layout dot razer.css that will be same as scoped style but because this is a in very small style and I have worked with vue.js as well so I liked that thing that we can have our script template and style on the same page so I like it this way but you are free to use this the separate scope CSS file okay both works the same way cool so we have this auth layout now we don't need this code block here we can skip this cool now on this page so we will remove everything before edit form and after edit form this is the only thing we need to have on this page but this time we will set at the red layout and that layout is going to be auth layout now let's run it so we will see the same structure we were seeing right now because now layout is applied and everything looks fine everything should look fine okay so this is this looks similar similar what it looks same actually so this is fine this is what we want and this top side this bluish color purplish color will fix this later this will come in the dot net Maui only this will not come in Blazers but we are good now right now if we press sign in you see the validations are working this is this validation message so username field is required password field is required and if we start entering something and if we move out of the field you can see now the outline is green color and we have a valid form fine so if the form is valid in this case we need to uh sign the user in so for this we will add okay and it started okay on valid submit we'll say sign in async if the form is valid and we are submitting it then we will call this method sign in async and this method will Define it here so we'll say private async async and here we are going to have our sign in logic and that logic we need our auth service because our methods are in that auth service to auth service and in here let's have a try catch block and here we'll save words result this is the method result a weight or service Dot sign in async and we will pass our model like this after this we will simply check if the result is Success that means user is signed in successfully we need to redirect user to home page and if this was not the case if this operation was not successful then we know there was some error so we need to show some error alert here okay now we will enter a different Zone so that alert show error alert so we can use our skip alert but we are not going to use JavaScript at all in this complete project so because we are on dotted mobile we are on mobile device so it's always a better idea to use the native alerts the native uh browse not browsers native devices alert so for iOS we will use ios's default alert and for Android the Android's default alert and same thing we should show a loader here right that something is happening so the show loader and this loader because we are on dot net mobile devices so it should be activity indicator now for this activity indicator we need to have this on our page but activity indicator is a xaml component Dot and mouse component so we cannot have it in Razer we need to have this activity indicator let me stop this we are going to make couple of changes we need to have it on this Main page.saml which is the first page which is going to be displayed when the app opens up and in this main page dot xaml we have this Blazer webview where our Blazer application is rendered there this is the only child so what we'll do here we will cut this we will add a grid here and this is the thing I will telling you I will OBS studio and this vs4 Mac right now this is not in debugging mode but still this vs4 Mac or my Mac is very slow and sometimes it's very frustrating the device is slow it is mostly in this Frozen State then the hot reload is not working so sometimes it's very bad please wait for an editor command to finish let's wait for this it is not going anywhere cancel okay great fine and we added this after this when we say grid so we'll have row and columns but for this particular case we are not going to have multiple row and column we'll have default grid which has one row one column that's all after this if we add this activity indicator control here now let's see what it will going to do first it will end the Blazer webview in the first row First Column that is the entire screen after that it will add this activity indicator on top of that Blazer webview because again we have the one row one column so it is these are going to be stacked so first Blazer webview and then on top of it activity indicator now first thing on this activity indicator let's move it to the center of the screen so vertical option Center and horizontal options Center now this activity indicator we have a property is running we can set it true and false as per our need so initial if we set it true it will always be true and if we set it false it will always be false but this is not what we want right we want it to toggle dynamically so we'll show this when required and after our long running operation or our any operation for which we need a loader that finishes then we need to hide it so for this we need to have some binding and when we say binding we need to have a view model so for this what we'll do uh let's create a new folder view models we are going to have this single view model for maybe single property only but still let's have a folder to separate everything so we'll create a new folder here and we'll say view model view models and let's have one view model only so we'll create a new class okay General empty class and we'll say it let's say app view model we can name it whatever we want but we are good with app view model and in this app view model it needs to be a view model when we say view model it need to notify that something has changed and to that we can use I notify property change interface and I'm not going to use Community toolkit mvvm because there is no point of adding one Library one additional library for single property where we need this I notify property changed so let me add the namespace for this within system.component model and now we need to implement this Implement interface so it gives one event which is this public event property changed event angular property changed in this we will have a method sorry not method we'll have a property of type Boolean we'll say show loader or we can say is busy like this and now whenever we are setting this value we need to notify this property change so for this instead of this property with that it gets set we will use full property what I mean by full property will have a backed field which will be this is busy and when we are getting we will return this is busy and when we are setting at that time we will have some logic here and that logic is going to be first we will check if is busy is not equals the value we are trying to set if there's the case we'll set is busy to value now this value is set but our main bit main page dot xaml this is not going to uh consider this new value because it will not know that if something has changed if this value has changed so for that we need to manually tell that something has changed for this we will use this properties changed event and we'll invoke this and here we'll say first sender which is this only and then we'll use this property changed event arcs it needs a property name and we will say name of is busy so now we are saying that when we are setting the value we will first set the value and then we'll trigger this raise this event and our xaml main page.saml it will internally subscribe to this event and then it will check if something has changed it will simply rerun this activity indicator re-render this and it will know that should it display it or not fine so we have set this app view model now we need to use this view model on our main page.assemble but before that let's register this app view model in our Maui program so here we'll say Services dot add transient will make it transient only app view model and namespace save everything now we'll inject this app view model in our main page CS file here like this view model okay let's add this to Global usings as well so we'll say Global using trip expense manager Dot View models like this save and now we'll have this app view model view model and we'll create no we don't need to create a separate field okay on this we will set The Binding context so using this vs setting a model for this page so for main page we are using this view model now we can use against stop responding we are gathering information dismiss and this is in this system okay fine on Main page.saml first we'll set the data type of this page this is going to be the app view model and that will come from a different name space so first we'll set a namespace so we can say VM which is view models and here we can say our trip action manager Dot View models like this and then we can set the data type for this app view model and now for is running if we set binding then we will have intellisense and we can have this property is busy so now if that is busy property is true we will show this this Maui is going to display this activity indicator and if that is false it will simply going to remove this activity indicator hide this activity indicator so this piece is done now we need a mechanism by which we can set this is busy true and false from our razor pages right so for this what we are going to do in maybe in our services or we can have it on the root only we will have a new class and that class we will use we will call it Maui interrupt the amount interrupt is fine so this class we will use this to AH connect blazer with dotted Maui so all the things when we pass when we want to pass some value from Blazer razor pages to Dot and Maui we are going to use this Maui interrupt class and not enter Oppo enter row interrupt and let's change the file name as well rename painter row fine and will register this class in Maui program as Singleton so not transit app view model should also be Singleton we need a single instance always in Trope and this is fine okay now in this Maui interrupt what we'll do we will inject the app view model like this so we'll say app view model and let's create a field fine in here we'll have methods first we'll say show loader and then we'll have one more method public void we'll say hide loader all right looter and these are going to be single lines so let's have this expression body and what we'll do we'll say app viewmodel Dot app view model is busy not sure we'll set is busy to true and from hide loader we'll say app viewmodel dot is busy too okay let's use underscore underscore and this underscore and then this underscore app viewmodel dot is busy we will set it false is busy to false this is fine but this is not the best practice so if we are modifying properties like this what we should have done in this app view model we should have some method here so for this is busy we should have this set as private so that we can modify this from here only from this class only now if we do this we will have error here because now is busy Setter is private we cannot set it outside of from the class so we should have a method here where we'll say private void and let's say toggle loader for toggle is busy we can do like this and let's say get the field here where we'll say is busy and from here now we will set this espg2 this is like this and now let's go here now we'll say underscore app viewmodel dot toggle is busy and this time we are saying yes from show loader his busy should be true and from hide loader this should be false is busy false like this practice and now we are good now let's use this Maui interrupe on our sign in page so we'll go to pages sign in page and we will inject this inject now interrupt okay let's name it Maui only and now when we say show loader we will use Maui Dot show loaders like this and then we'll have a finally block or let's do this we will set we will hide loader if there was some error so after showing the error alert we'll say hide loader or if we had some exception from here also we'll show error alert and then hide the loader so we'll say Maui dot hide loader right now we don't have this loader service we'll see this in a bit but for now let's do one thing let's have a delay here so that we can see that loader so we'll have a delay of let's say five seconds foreign okay let's try it if we can see this activity indicator this loader run it we have some error there is no argument given to the main page yes so for this main page where is our main page main page is here we are injecting this app view model but this main page this is not registered okay directly the way we use main page is we call its instance from this app so we need to pass that view model here and then we need to have this app view model injected to this app so we'll do this now we are injecting this app view model to app and from here we will pass this view model so this is going to be the same instance let's run it now okay now let's try sign in add some values and sign in and you can see that this loader right activity indicator is here and after five seconds this is gone so that means this thing is working now we have successfully established a connection between our dotted Maui the mobile device side and then our Blazer razor Pages side so we created this Braille now we can use this for other things as well so what other things so what other things right now we have this activity indicator and after this where is moving truck yeah this one we know we need to have alert messages as well so for that also let's add some methods in this small interrupt public async task will say show error alert async okay and we'll get error message and we can optionally get error title which will set to error default okay okay now we'll use our weight app dot current dot main page dot display alert this method so this is coming from dotted movie on this first we can set title which is error note error we should use this title only then message we have this message and then button will say okay like this so show error alert this is fine then let's copy this one more time and here we'll say sorry show success alert success alert message title and title we can say success and then it will also going to be the same cool we'll keep on adding methods and things which we'll need uh on the go whenever we'll need something we'll add to this class fine now let's go to our page sign in page and we have this show error alert so let's display this error alert so here we'll say outfit Maui dot show error alert async and here we can say okay we could have the error message so we'll say result dot errors if this is we got this result order we'll display this if somehow we could not get this we'll show some default we'll say error in signing signing in something like this and we are good same thing we'll do here a weight Maui dot show error alert async and this time we will display ex Dot message because we know that we have this exception so we'll have the CX Dot message now let's remove these uh helper comments now we have only one missing piece which is this redirect user to home page so for this we will inject navigation manager inject navigation manager let's call it navigation manager only and from here we are going to use navigation manager dot navigate to the page is going to be home and this time also we'll set this replace to true because we came to the signing page if we added username password we clicked on sign in we redirected to the home page and if we press back button from there we should not come back to sign in page because we are already signed in pressing back is not signing us out right so when we press button it should directly come out of the app because there is no previous page in that case and if we open the app again we should be directly landed to the home page so we should use this replace true so that this current page gets removed from the navigation history cool so this page I think everything is fine on this page let's see the error alert if this error alerts para alert comes the way we are expecting it then we'll work on sign up screen because we cannot sign in before signing up right we need to have some user then we'll use those credentials to sign into the app app is here let's try sign in we have errors add this we have sign in loader for five seconds and now error invalid incorrect credentials this is coming from iOS from this Maui intro right okay everything looks fine before continuing let's try this same thing on Android emulate let's see how it looks on Android okay and we have some strange errors so let's uh clean the solution stop and read them looks like this is working no one errors and what is the error there is no error why deployment will then let me keep on trying java.io.io exception requested internal only but not enough space so there is no enough space in my emulator let me clean up the emulator device okay so it came I uninstalled couple of previous apps and now we can see this sign in username we can add it and now you see we have a problem here on Android this is going behind of this uh keypad so for this there is no native solution from Norton Maui side but I found something I'll share with you but first we want to see we click on sign in and we can see this activity indicator this is native to Android and then we can see this alert so this interrupt is working on this uh this Android emulator as well now for this thing the keyboard is overlapping the screen for this I found issue on the GitHub then I found one workaround one solution for this so I'm going to quickly copy and paste that and I'm going to add the link of that particular data issue page so you can check that out so this is the issue my blazer view input Blazer webview input covered by keyboard so this is there and then there is no direct support but there is this I'm using a method.net 7 so this is the thing I tried and it works so in platform Android we can have this class my name is different I used a different name so I'm going to link this page in my description so you can check this I have copied this I named it Global layout util and I pasted the code here the direct code and now we'll use this Global layout util here in our main activity so I am in platforms Android main activity.cs file because this thing is on Android only so we need to fix it on Android only so here we'll override a method which is oncreate again fine so after this we will say Global layout utils Dot assist activity and we need to pass the activity so we'll pass this save everything and let's run it on Android again this time it should work foreign let me copy the complete signing page just uh excluding the page directive the first URL copy everything go to sign up page paste everything and now we'll make some tiny adjustments first instead of sign in model we'll use sign up model this method will rename this to sign up async sign up async copy change this method to sign up async after that we'll use the sign up async method like this error in signing if we'll say error is signing up fine after sign up also we'll redirect user to the same home page and this button it should say sign up username password and before this username and password we will have one more field which will be name so underscore model dot name and name model Dot name okay and this welcome back instead of welcome back we'll say something like let's say hello and we'll say sign up to prepacks like this save everything and it should work let's check on iOS sorry app is coming and we cannot go to sign up page because we have not linked this page right so from sign in we need to link sign up and from sign up we need to link sign in okay so for this after this edit form let's create uh let's say p we'll add couple of classes here and we are on sign in page so we'll say if you are new to tripex then you should sign up so for this we'll use nav link href so href it will navigate to sign up page and we'll say create account or we can say sign up let's have create account only and on this P we will add classes first we'll move it to the very right of the screen so text and and then let's have some margin from the top cool let's copy this P tag and go to sign up page and on sign up after edit form we'll do same thing but instead we'll say already have an account if already have an account on tripex you can sign in so we'll change the url sign in and instead of create account we'll say sign in save everything and let's run let me pull up the simulator app is coming we can see create account if we tap on this we are on sign up page from here we can see sign in so the linking is working everything works fine now on this sign up let's quickly create a new account let's say about username AP password AP sign up and we are on home page and we can see this loader because are we not hiding this loader after this okay after this also we need to hide this loader so for this what we'll do we'll hide this loader in finally block cut from here add here and let's remove this and let's do the same thing for sign in page sign in will remove this loader hide from here from here as well and we'll hide it in finally block like this cool so everything should work fine now now if I stop it and I run it again this time this should directly go to home page because right now in auth service we have this data in our preferences and the sign out property which is signed in property we will have this key already and we have that logic on our index.raiser page that if user is already signed in we will navigate user directly to the home page let's say [Music] and we are on home page you see cool so after this sign in sign up flow setting saving UI everything is working and we are good with sign in and sign up now we will work on this sign up page sorry note on sign up this home page but before doing that let's fix the the status bar color so we'll go to main page dot XML so this background color dynamically Source page background color instead of this we will remove everything we'll set it to white color and then we'll add a one nuget package for changing the status bar color so for this right click on the project manage new get packages browse and here we'll search for Community toolkit Dot Maui Community toolkit Maui this one first one so we'll add this package adding accept we'll use this to change the status bar color and we will have some toast messages maybe snack bar I don't know we'll see so after installing this we need to use this use Maui Community toolkit in our Maui program so let's go to Maui program Maui program dot CS now in here on this Builder will call this use Maui Community toolkit and we are good now now let's go to go back to main page mainpage.saml here first we'll add a namespace for Community toolkit so let's say toolkit only so it will be this one schema.microsoft.com.net slash 2022 slash toolkit this one and on this we'll say content page dot behaviors and here we will set status bar Behavior so first we'll set status bar color and we need it white and then status bar Style because the content is the background color is going to be white so we'll say the status style dark content so that it shows the the time and all those default content from status bar in a dark color save everything and let's check it out on both first on iPhone okay it is coming so you saw there was this white screen for some time and then it came so for that white screen we'll fix it but right now we can see the status bar color is white which we need which we want right so this is fine stop this set pixel 5 Android emulator let's see it on Android emulator so you see things are working and this time there was white screen for couple of seconds not couple of seconds uh very small amount of time but we don't need that white screen there should be at least some indicators for that what we can do and by the way on your screen you will see a small loading text here on top left and that is on my screen that is not coming because I cleaned that up so you will see that from triple W root index.html so this divid app this thing so there you will have this loading text I remove this loading text so we don't need we don't see anything now after this footed white screen what we are going to do we will display the device's native activity indicator by default so for that what we can do we have our app view model this we can set the default value to true so this is default value now we will see this loading indicator this activity indicator when the app launches but it will going to be on the screen always but that is not what we want but first let's see if it comes on the screen then I will tell you how uh what is the correct approach to hide it and when should we hide that okay it is coming let's say this activity indicator and it is there we cannot see anything nothing is happening that is because Now You See It came it took some time to load the Blazer app so Blazer app loads it takes some initial time to set up everything then it comes so now we are displaying activity indicator that is fine so user can understand that something is happening the screen is not blank not frozen after that when this page comes up we should remove this activity indicator so we need to have something that can tell us that Blazer app has initialized and when Blazer app is initialized then we should hide this loader so for this what we can do we know that the first razor page inner app that will come up that is going to be in Pages index.tracer this page right so when this page comes up we can come here and on initialized and we can say we can inject our Maui uh interrupt this and here we can say Maui Dot hide loader when this only initialize work that means app is initialized and now we can use this hide loader so let's check it one more time I am restarting the app this time we will see that activity indicator then when app loads then this activity indicator will uh be hidden from the screen will hide automatically okay happy coming we see activity indicator and now it works right cool stop it let's check it on iPhone run [Music] okay we see this activity indicator and then this home page quickly cool now let's start working on home page let's see what we have on home page first so let me open up the app demo app oh come on what is happening okay let's see if I have this on iPhone yes I have it this so first we need to have this main nav bar the stop nav bar so let's first design this and if you remember somehow I'm not able to open this one uh Android emulator right now um let me check if I have it here somehow things are not working on Android okay let's so the thing is we need to have first we'll have this had done this uh top never then we need to have some mechanism by which we can detect that if this is on iPhone or on Android because on iPhone we will have this text in the middle in the center of the screen but for Android we will have it on the left side on the screen so for this let's first start working so and we will have the same uh tab bar for all these pages so home page trip space settings page so this thing is common and this bottom tab bar this custom bottom tabs these two things are common so we should have these as a part of layout okay so for this we'll come here and we have dot DS store let's remove this file first delete okay we have in shared folder we have this main layout let's modify this main layout to have this header and this bottom tab bar minimize everything here first thing before body we will add a div with class it should be 100 with position fixed position again let me stop it first the debugging position fixed then we'll have some padding P3 then we'll have some margin bottom mb3 we'll have background color as white PG White and then we'll have some shadow shadow SM like this then let's add a class We'll add some custom styling to this top never save everything in this let's add styling to this tab Top Nail Bar we already have main layout.raser.css so we can have that thing here the CSS or we could have it on page as well with scope tools so this top neighbor what we'll have first we'll have a fixed height to this and this should be dynamic so for that we are going to add a variable here CSS variable we'll call it let's say never height and we'll use this 50px then on this top neighbor we can use this neighbor height like this and let's have a z index of let's say 10. and we are good with this so top neighbor it should work top neighbor now we'll have one div here with h stack horizontal stack with gap 3 to have some default spacing these glasses are coming from bootstrap again you can read about this hatch stack in this we will have two items first we'll have a header let's use H3 and on this we will have class m0 we don't need any margin from any side and we will make 800 percent width and here we are going to have our title so tripex manager after this we will have that icon if you remember that was user icon so for that what we can do we can have a box cycle we already have so BX b x user Circle this is the class and then BX SM to make that icon a bit bigger and then text dark to make the content as uh black basically on white screen which should be I think default but let's use this save everything after this we'll have this body now because this is position fixed this first part now this body it will going to be behind this to the first section of this body it will be hidden because of this position fixed so we need to tell this that the content should start after this div okay so that because the position fixed sticks on the page and if we have some content it will going to be behind of the Tabor that is not what we want so for this what we'll do we will have a div here we'll say div class let's say body content like this and in this inside this body content we are going to have our complete body and for this body content we'll add some styling so let's go to this main layout tracer.css and here we'll set this body content and on this body content will say padding top should be the height of top never which is this variable now you see that's why I added this as a variable so that we can reuse this same thing and if we tomorrow if we want to increase or decrease the height we can simply change it from one place we will change it here and it will be reflected throughout the project for all the CSS and everything so it's always a better idea to have uh the CSS variables for these kind of stuff fine save everything go back and let's try it run I am on iPhone let me open up iPhone go to home let it build and start it is coming up okay okay and we can see this cool so everything looks fine but this home page is still behind this will fix it in a bit but for now let's see everything looks fine tripex manager everything is fine but for iPhone this text this should be in Center so for that we need to uh have some way to check the device here and again that is from Maui side so we can add something to our Maui intro class and that something is going to be in here let's add a property so we'll save prop and here we will say Bool let's have two properties the first we'll say is Android for this we can have device info dot current dot platform if this is equals to device platform dot Android then we'll say that this is Android same thing we can do for is IOS is iOS iOS like this so now we have this thing in our Mao interrupt we can directly check those so let's go to our file and it is again oh my God okay we are here on this H3 we will add a condition that condition is going to be first we need to inject our Maui interrupt we'll call it Maui only and here we'll check Maui dot is IOS if this is iOS we'll use text Center class for all other we'll use text start class save everything and let's run and check it on both the platforms first let's see it on iPhone it should be in Center the heading okay it is coming up activity indicator and now this is in Center pool let's stop this and try it out on Android start various Android is here okay it's coming up activity indicator page we need to create account here first create account name okay AP sign up and we are on the home page and we can see this tripex manager on the very left so this is working on both the screens on Android it is left aligned for an iPhone it is center line that means this condition Maui dot is iOS or is Android this thing is also working maybe I need to empty the bin and restart Mac it is loading and this thing cool so everything looks fine now next we'll work on that bottom tab bar and then we'll start adding content to this page so for bottom uh tab bar we'll have a div here so Dave class deflects display Flex justify content Center and let's have it with hundred percent inside this will again have a div with same display Flex justify content this time align item Center as well and then we will have VW 90. so 90 percent of the width so this class if you remember I showed you I have created this class in our app.css file this vw90 fine after this let's have some padding P2 some margin from x axis so mx1 and a bigger margin on Y axis top and bottom we'll use this after that we will have the background color as busy success so greenish color then we'll use one class from uh bootstrap which is busy hyphen gradient so it will uh uh add a gradient effect to this then we have this position fixed rounded pill or some rounded corners and then a large shadow this all we need so this is going to add the the tab bar now we will start adding the content to this but before that let's have a custom class bottom Network same like this we will have this bottom or let us say bottom taba tab bar tool save everything let's add some styling to to this bottom tab bar and this we can give in main layout dot laser Dot uh CSS file because we have this file so let's utilize this only so for this what we'll do we will simply set bottom five pH we already said position fixed and when we set bottom it will be at bottom we set the width already the VW 90 so it will be a 90. and then let's have a shared index of same as 10 for example fine so we are good with this now we'll start adding our menu items to this fine so for menu items we will have label as a container on this label we will have rounded pill PX 3 py1 text White m0 margin 0 and then on this also we'll have display Flex and then we'll have Flags column because we need items in vertical order so items means we will have icon and the text so home icon home text trips icon then trips text so that we need that in vertical order that's why we are using Flex column and for this when we are setting Flex column then let's use a line item Center to move the items to Center and now let's start adding icon and the text so we are going to use same box icons so first one is going to be home so PX home home file and on this one we will use margin 0 not outside inside only m0 and P0 like this and after this I we will have our text which is home and we'll use our class fs12 to make it 12 pixel so this class is also coming from our app.css save everything let's try it out so let me select iPhone and let me run it let's see how it looks then we'll add other items other menu items you're setting app is loaded and we can see this but at the wrong place first thing this should have been in the center so what are we missing just T die content Center it should be justify I had a typo after this it should be at the very bottom so we have position fixed this should work we have bottom 5px and this is not working is it actually working let's have background color red important let's rerun I'm just making sure that this style this is working Main layout.raser.css app is coming up and and no this is not working okay so what could be the issue let's check so first we will check if the name with same so main layout.racer main layout.raser.cs's name is same that's why it is showing like this if this is fine then next thing we should check our index Dot HTML if we are adding the all those code Styles those gets added to this thing okay this is the problem so I have this triple x dot styles.css but right now the name of our project this is trip expense manager so let's copy this name and it should be this so if you have created project it will be automatically fixed but because I already created the demo project so I uh moved some stuff from here and there that's why it was in inconsistent State and we saw this uh incorrect behavior let's try it out it should work this time okay it is loading activity indicator and boom yes it is working cool so after home let's add other menu items as well [Music] main layout main layout.raser so let me copy this label I'll paste it here and the name I'm going to use trips and the icon we are going to use so I could not find any other icon related to traps what I found there was this food menu icon let's see how it looks trips everything is fine we'll add that selection logic later but first let's have UI ready then we'll fine tune this and we'll learn about other Concepts as well okay and this is in Center it should not be in center right it should be so on this second div which is the wrapper of all these menus it should be justify content between save let's add all the item all the menu items first then we'll see it third and then fourth so third one is going to be that plus icon and on this one we are not going to have any text so we will simply have an icon and the icon will be BX Plus Circle and this time because we are not having the text it will be very smaller so we need to make this icon bigger so we can have all these Styles SM MD LG all these sizes so you can check the box icons documentation box icon CSS documentation you will get all these classes there so I am using a bigger icon and then the last one is going to be our settings and the icon we'll use that is called save everything and rerun app is coming and we can see all these items and everything looks great okay cool now first let's add at least these or maybe all these Pages strips add trip and settings let's add these three pages then we'll implement the or tapping logic switching between these screens will add that logic let me stop it and I'm going to add the all these pages so in Pages folder we'll create a new page so new file uh asp.net core Razer component first we'll have trips page I made typo let me rename this trips page like this then another one for create reply so we'll use Save trip page we'll use the same page for ADD and edit both add and edit trips then let's add one more new file razor component and this is going to be settings page fine let's add the page directive routings for all these so save trip for now let's have trips dot add let's do this and we'll say here save trip so that we can see that something is happening on settings we'll use page slash settings and let's change this head into settings and then we have the strips page here we'll add page directive with trips so this is going to be URL route for this page and trips so we are good let me save everything and now let's go back to our main layout from here now whenever we are tapping any of these we should navigate user to that specific page so for this first we need to have our code block first one thing we could have these as nav links but then we will need to add so many uh Styles classes so let's skip that part and then we want uh to control the this nav link so we will always programmatically navigate user from here and there inside this app so we have nav link only on sign in and sign up page we are not going to have enabling inside the complete app rather than those two pages I'll explain it later why we are doing this okay now first let's have a method here so we'll save Private void and let's say go to page and then we'll get page name here now we need to inject navigation manager because using that only we can navigate user around so we'll inject navigation manager we'll call it navigation manager only like this and then we'll use this navigation manager dot navigate to and then this page name now this is the page name this is not the URL so we need to have some uh map or some State here or some collection where we'll have all the mapping so what I mean by mapping is we have page names which is settings then trapes home all these then we have the uh urls so let's create a private static I dictionary and we can have string and string we'll say page name or let's call Page Maps Pages map like this new dictionary of spring and string and now we'll have this here so we'll have home and trips and settings so for this let's have constants here private const string home you could have these in maybe some separate class four constants but I don't think we are going to use this anywhere else if we are going to use these anywhere else then we'll simply move this to the separate class but right now you using this here only so I'm having here only okay so we have home and then second we have trips then third we have settings settings like this settings and trips now instead of hard coding this is home we'll use this home and the URL for whom is this slash only then come strips trips and we know the URL for trip Scripts then third one we will have settings set things and the URL is going to be settings like this okay we have this now now we can directly use this underscore Pages map and from on this Pages map we can use page name and we'll directly navigate to that particular page so this is fine and here we are not using that replace true that is because if we are navigating to the next page and if we press back button we want user to come back to this page because this is the previous page in that case so we want this uh hierarchy this navigation history basically so let's use this go to page or on this first label we'll use our own click and on this we will use this approach we'll say go to page which page this is going to be home page this is a constant which we just defined copy let's do the same thing for trips trips and let's do the same thing for the last one settings now this one this uh create one we don't need that thing we can have but the point is I am having this separate because if you remember the demo app we can have the selected Logic on all these three pages only note on create page so create page is uh we could say an internal page backable page where we will have that back button and we will not show this bottom tab bar or main navigation bar basically on that particular page so this will be an inner page then stacked page that's why I'm not having the same logic I'll explain it when we'll reach at that point so for this also we'll use Save on click but this time what we will do we can directly navigate use user or maybe let's say let's have one more method here we'll move this method to some helper class later so we'll say let's say go to Inner page what I mean by this is I'll explain it later right now let be with me only so private void go to winner page and here we can say we can have the URL directly from here we'll say navigation manager dot navigate to URL okay so we'll use this go to Inner page on this third one this plus Circle create a trip page and here we will pass the URL which is going to be trips slash ad in this case because we are using double quotes it is not able to figure out so we need to wrap this complete on click [Music] um at the rate and then these braces like this so I think everything looks fine now let's try to run it and let's see if this functionality is working we'll work on UI after this first let's check the functionality app is coming and we can see this nice looking bottom bar and then we are on home we are on trips we cannot see anything and that is because it is being hidden from this right so let's to increase that padding top never height so we'll say calci never height plus or maybe instead of plus body content padding top is this why can't we have let's try to add some margin from the top so on Main layout where we have this body content margin top five let's see rerun this is not what we want okay so we cannot have this margin top here let's try to fix it using some other approach margin top body content this is outside of this position fixed still okay on padding top let's try to have maybe uh some more pad padding let's say 20 PX we'll check what will be the best way to do this but first let's get it working first and again it is at the same level okay okay what we should try we should have this padding on body not body content let's try on body directly if we do this let's see if it works so the CSS styling position this is always trickier and I'm not perfect in UI styling but I can get it to work using some hit and try methods okay again this is not also not working let me try to find a way so I figured it out somehow this is uh these styling these are not using these CSS variables right this is column root we have we are defining these here but if I add the Direct Value then it works so I tried another approach and that approach is let's remove this remove this we can move this these PSS variables to the very top that is app.css so we'll have our variables here if we are doing this we don't need this ABC green I was just testing it so now we have this variable here and we are using this variable in our uh Main layout.raser.css and now if we tried it should work I checked the background color from here let's see cool we can see this home page here and if you go to trip we can see trips settings we can see settings so this thing is working and if we click on this plus icon then we are going to be on this save trip page so everything works fine now let's implement the headers for this and right when we click on let's say trips then this main header this should change to trips and when we tap on the settings this main header it should change to settings right so this thing we'll do next now how we can do this when we are tapping on these things we need to somehow have a mechanism by which okay there is one more thing uh I don't know how to use back button on this Android sorry iPhone Simulator on Android we have back button so we can use that the point is uh you might be thinking that we are clicking we are tapping on these icons so we know on which icon we are tapping so we can simply uh change this heading accordingly but then we will have a problem and that problem is going to be we can also press back button and when we press back button then the screen so for example right now we are on the home screen if we go to trips page now we clicked on tripspace it will be trip but now if we press back button at that time the automatic navigation it is going to redirect us back to the home page but we have not clicked on this home icon in that case our logic is not going to be triggered and we cannot set the header in that case so we need to somehow have a mechanism by which we can simply use uh some publisher subscriber method basically so we'll use events and from there we will handle that on what page we are currently on and we will set the header accordingly and then there is one more thing to it if we are on home page this home icon button this should be selected if you are in trip space this should be selected so for this selection as well with the tapping and with pressing the back button for both the cases it should work so this is the thing we are going to work next now this is going to be a global state which can be used not can be it will be used at couple of play Pages layouts and we can say at so many labels so many pages so we should have this state accessible throughout our app so what we'll do we'll create a new folder new folder let's call it states and here we'll create a new class file new class and we could say it as App State okay and in this app State we will start adding items so the first item is going to be the selected uh menu item right we have those four items from where we can select three at least so for this we will have a property here so public string and selected menu item and let's have it get and private set we will use a helper method to modify this selected menu item uh property okay let's have a default value as home because the default selected menu item is home after this we will have a method here so public void let's say change selected menu item and here we'll say menu item or page name page name like this and from here we'll say selected menu item equals this page name now whenever we are doing this we are modifying this property okay first thing let's use this on the main layout let me close everything close all but this okay then let me open the main layout here but before that let's add the usings for this app State this is in this name space so we'll go to underscore imports.tracer and we'll add a using statement here it's using this thing so that we can directly use it on our layout page save everything okay and before that let's do one more thing we'll register this to a DI dependency container in here we'll say like this only We'll add it at Singleton because we need the single instance to be used everywhere and let's add these two Global using server so we'll say Global using trip expense manager States right this and we are good now so now let's go to main layout and here we will inject this inject App State and let's call it app state only we have this App State now this thing this tripx manager so here instead of directly hard coding this we can use that App State so let's create one more property into this so here we'll say we have two approaches okay that we can directly use this selected menu item or we can create a computed property here for the page title and here what we can do we can apply a switch statement on the selected menu item so we'll say selected menu item switch and then if this is home the selected menu item is home which is default in our case we will said the title to District X manager and if this is not the case for all other cases we'll use the selected menu item directly whatever it is and then we can use this page title here like this App State DOT paste title App State DOT page title like this cool now whenever we are tapping these button so go to page method whenever we are calling this go to page method we are going to navigate this and after that we need to set the page name so we have to approach either we can do here only or the best place to do this would be individual pages so if we are on home page we will inject App State and then we will override on initialized method maybe on initialized racing because we are going to need this to fetch data from sqlite so let's do this protected overwrite task common initialized let me add a sync as well and here we'll say App State DOT change selected menu item or we should change it to set selected menu item right so it should be home now we are using this hard-coded strings at multiple places so we should consider four constants in this case so we could have those constants anywhere or maybe let's have those or not root only so what we'll do we'll create a new class globally and we'll name it new class we'll say app constants tabcon stands fine we'll make it static public static class and in here we'll create a new class public class we'll say menu items like this public static class and then we'll have menu item names so we'll say public const string home it will be home then public cons string trips it will be trips after that public cons string settings it will be settings we'll add others if required but for now we are good with this one so now first let's go to home page so instead of setting this directly home we will set app constants dot menu items dot home let me copy this we'll go to App State and the default value will set the same thing app constraints menu item home and same will go here when we are setting the page title we'll do this so instead of checking that hard code we are doing this and in that case we can also move this tripex manager to our constants so we could say directly in the app constants we'll say public const string app name tray packs manager like this manager and then we can use this here so we will say app constants dot app name like this save everything fine now first thing let's change this change selected menu item to set selected menu item so we'll change it we'll rename it set selected menu item okay now let's go to main layout App State page title is fine okay now we can remove these because we are not using this we are using this from app constants now so instead of doing this we'll say appcons Dot menu items dot home copy paste and paste okay so for these page URLs we are using these now these hard-coded strings as well we'll use app constraint menu items.com so go to page go to page like this cool now let's go to home page that selected menu item this is fine let me copy this or maybe before that let me copy this inject App State we will use this on our trips page and on our settings page and we'll use the same override on initialized async for both trips page and here we'll set Upstate dot selected menu item it would be menu items Dot trips and then for settings we'll do the same thing just we'll change this menu items dot settings like this save everything we are good and now if we go to main layout everything should work fine we tap on home page by default home page is selected we tap on trips page it will be this it will call this go to page this go to page it will redirect to the slash trips page and on slash trips page we are setting the selected menu item so it is going to change the selected menu item in App State where is your app state that is here it is going to modify this and after that on Main layout we are showing this app State DOT paste title so now everything looks fine but there is one problem the problem is how would this main layout know that this page title has been changed and we need to re-render this that because this page title is App State DOT page title this is not a property of this main layout so how Blazer State management works if we have some State on this page only so when we say state it could be property or variables which is defined in this code section if we are directly modifying those from this component then Blazer knows that this value has been changed and I need to re-render this component but in our particular case we are modifying a value which is not a part of our this main layout this is a part of a separate class and we are modifying it from separate class only the place is different the class is different so in this case we need to somehow manually tell this main layout that this value has been changed you need to re-render and for this Blazer gives us a method which is state has changed this method so we can call this state has changed method manually to trigger the re-rendering that you should re-render this now the main point comes okay we know that we need to re-render but when when means whenever this value is being changed so we don't know on this main layout that when this value is being changed so this change is happening inside App State only so we need to somehow notify main layout that something has changed in App State so when we say notify we have two different approaches first we could have an event here so we'll say public event event handler and if we are passing something so let's say in this case we are modifying page title or maybe menu item so we could simply use string we'll use the new menu item and we'll say menu item change or select state menu item change something like this selected menu item change like this and whenever we are modifying the selected menu item like this after this we will simply invoke this like this and we'll set objects under this and E this is the string value so we can set this page name like this and on Maui uh sorry on mainly outside we can subscribe to this we can add an event handler to to this so what we can do in here we can override our own initialized method protected override on initialized oh my God what is it on initialized okay and in this protected override void on initialized okay here what we'll do we'll say App State DOT selected menu item changed plus equals we can simply call state has changed and which is not going to work directly we need to create a method so we'll say private void uh on selected menu item changed first object sender and second selected menu like this and in this we will simply call status change so we can remove this and directly say state has changed and then we'll call this add this event handler here so now we have uh joined the pieces now what is going to happen we have subscribed to this change selected menu item changed so whenever we are navigating to some page in our case let's say we are navigating to trip page on trip page we have this app state DOT set selected menu item here we are calling this method and if we go to this method here we are saying selected menu item is this page name which we passed from there in this case strips after that we are raising this event when we raise this event it will automatically go to this main layout here it will be triggered and on this we are saying state has changed this means you should re-render the page and when Blazer is going to re-render it it will come here at this line number 11 it will say App State DOT page title and the spaced title is a computed property this page title so it will automatically come here it will check selected menu item which is trips in this case so it will go to the second case and it will set page title to trips and then on the main layout we will see trips so this is how all of these things are going to work now it will work fine there is only one piece whenever we do any event handling like this we should always free up these event handlers we should always remove the event handlers when this component is not uh on the page basically it is destroy disposed so for this whenever we are doing this plus equals to we should always do minus equals to and for this what we will do we will implement High disposable this is the interface and it gives us one method which is public void dispose and in dispose we will do the opposite of this here we said plus equals in dispose we'll say minus equals so you should remove this one selected menu item change now this will not going to trigger cool so everything looks fine now it should work as expected but we are going to change this approach this Zone selector menu item change this thing later but for now let's see if it is working as we thought it should work let's see so okay first let me set iPhone simulator run it app is here so we can see tripex manager now click on trips and we can see the heading and the main title is being changed on settings as well so this is working as we expected it should work cool if we go to plus icon then we can see the strips only we'll work on this later when we'll work on the inner page layout but right now we are good the thing is working as we expected should work now next thing is whenever we are on some page it should show these trips in this case we are on trips page so this trips icon there should be some visual indicator to just show that this menu item is selected right now let's do this so on Main layout now we know the selected menu item right so here what we can do we have two approaches we only have three main menu so we can simply create these three properties if we had multiple and more menu item then we could create a method and we can pass the name and then it will return true or false in this case but we'll make it we'll make it simple so we'll create simply three properties here we will say is home selected selected okay so here we'll check what will we check we will check app state DOT selected menu item if this is equals to app constants dot menu items dot home so we'll check this thing okay let me copy this two more times second we'll say is trip selected and then third one we'll say is settings selected and here we'll say trips and third one we'll say settings and then we can use these menu items directly on our template so where is this here so in order to show the selected thing we will work on two different things first is we will change this icon so for home we will add a condition here so we'll say is home selected if the home is selected then the icon we are going to use it will be a solid icon so it will be variant of box sorry this home icon so it will be bxs which stands for box icon solid a hyphen home and the default will be whatever default we had which was BX home and now we can remove this px1 from here okay the same thing we'll do for second one so here again we'll add this condition and this time we'll say is uh trip selected if this is selected we'll do bxs boot menu and if that's not the case if it is not selected we'll use the previous icon which is this BX food menu like this same thing we'll do on the fourth icon which is the settings so we'll add the similar Condition it's setting selected then we'll say bxs COG and if it is not selected we'll use the previous icon BX curve and we can remove this cool first this thing we are changing the icon after this we can have one additional class 2 this label this main container if this is selected so it will look good basically so for this what we are going to do after you know inside all these classes after all these classes we will add the same condition is home selected if home is selected we'll add a class here which will be Shadow LG so a large shadow if that is not the case we will simply use a lighter white color okay and then we can remove this text white because we are going to use a lighter color so that we use shows that this is not selected now this light White this color class does not exist in the uh in bootstrap so we will create this class in our app dot CSS because this can be used at multiple places or maybe if this is being used on air only let's add it to Main layout.raser.css light white so here we'll say color and then we'll use a color which is BBB and we'll add this important so that it will be applied only save everything come here light white fine now let me copy this condition we'll use this condition for all other labels as well so here we'll use same thing we'll just change this condition to is trips selected and then same thing we'll do for the fourth one like this and it should be is settings selected like this so now we are good the only thing is this third one we are not having anything here so we should change this text white to light white so that it always shows this some grayish color some light white color cool so looks like this is also fine let's try to run it and we'll see it in action okay now you can see we have this selected but it is in black color the first one icon is changing text is changing to white but first one is in dark color and why so do we have something there light White light Shadow LG oh we should have this text White we'll have this text white as default to all three items we from where we are navigating to the main pages and when we apply this light white it is going to override the text White okay let me restart it okay okay now we can see this home selected with white color trip selected setting selected so everything looks fine now cool okay now let's start working on this home page so for this I'm going to stop it because we are not getting hot reload so there is no point of having it right there we'll move to home page dot Tracer did we already created the service so let's go to Services we have auth service C data service so after auth service let's create a new service using which we'll do all our trip related action so in Services folder we'll create a new class which we'll call Trip service and we'll inject our database context to this context and we'll use this underscore context underscore contact like this save everything and first let's register this trip service in our Maui program we are going to register it at Singleton because it will be used at almost all the pages let's cut it from here and have it here so we can add it with any there is no it does not make any difference but I am keeping these separate so these are related to direct database these are related to our services first ones are the global things that's why I have these in a separate service call with but that does not make any difference you could have these one by one you could have this chaining for all of these so it does not matter okay so looks like everything is fine now let's go to trip service and here we will start adding our methods so first thing we will let's add all the methods first or maybe uh start from one by one so first we need to have a list of recent uh trips because on the home page we are going to display the recent trips okay so for this we are going to use private async task I numerable of trip so we'll say get trips async and here let's use paging so we'll say int page number with default value as one and then end page size or we could call it count with some default items the 10 will use the default 10. now when we say recent so we are going to display trips in descending order of created by okay so for this if we go to our database context I don't know if we have any method there so let me go here and we do not have this pacing method or the order by methods so we can create this if we want maybe I'll update this in that Repository if not we could use another approach and that approach is going to be we can simply get all get table listing we can modify this method so private async task async table query I table T table get table async we will make it public and we can directly work on this object so what we'll do here we'll say word query equals a weight context dot get table async and the type of table will be trip now we have this query now we can apply our parameters on this our conditions basically so here we will say query Dot order by descending T dot Creator what is the name added on then we'll skip we'll add paging so page and O minus 1 multiplied by count this is the classic paging stuff dot take count so this is the paging now from here we'll simply use two array singer we can use to list async here we'll say what trips equals this and we can await it and now we have this ready and we can return the trips directly or we could directly return this like this return without having this extra variable like this save everything and we are good now so we have this get trips async after this let's add the save methods as well okay so here we'll say public async task trip and we'll say save trip async sync we'll use single method for ADD and update booth then we will expect a trip object from here so first thing we will check if trip dot ID is greater than zero or it is equal to 0. so if this is equal to 0 we are creating a new trip and if that's not the case that means we already have a trip we are going to modify it so modify and exit string trip like this and after doing everything we'll return the strip object directly like this cool so when we are saying create a new trip we'll simply say a weight context dot add item async a type of item is going to trip and we can pass this trip object directly we are not using some different model for this no view model that's why we are directly operating it if you choose to create a view model then you need to map this so that view model to this trip database object basically a weight context dot update item async and here we are saying we are updating this strip this object so everything looks fine now cool and if you want to have exception handling we can have cut everything add track h and instead of returning trip we can return method result but from method result we do not have any data right so let's create one more variant of this method result so here we'll say public uh let's make it as a class method data result or maybe method result with data it's up to you and we'll make it generic so that we can use any type of data like this and then here we'll have the same properties first we'll have a Bool it's success then we'll have a nullable string errors and then in this we will have one more which will be data for this type of this T data and let's use the same two methods change the type so it will be if we are setting the data visual success so we should pass the data let's add Constructor also so we'll create a Constructor in this generate Constructor with these three things tool and we have this data so we can return true for each success null for error and data for this data whatever we are using and for fail let's use the same return type string error in this case we will not have any data because the method call was failed so there is no point of having any data so here we could simply return the default value for data whatever it is so this type we are going to use this let's go here and instead of this we'll use this method data result and the type of T data is going to be tripped because we are going to return trip from here right so here we will return method data result of type trip dot success and we are going to add this trip here looks cool if we are in exception state if we are in catch then from here we can return method data result of type trip but this time we'll return with fail and the message will use ex Dot message like this okay fine so saving is done and getting the complete list of trip system then we can have one more four edit editing purpose right when we are going to edit some existing trip we need to fetch the data for that particular trip so for this we'll say public async task and from here also we could use method result or in this case we know we are not exposing the URL address bar in our app so the URL will be whatever URL we are setting right so we can be sure that there will not be any invalid URL but still if you want to be double sure you could return a method result but in this case I'll directly return the strip so we'll say get trip async and in here we will expect a trip ID okay then we can simply patch this from the database and return this directly so we'll say return of fate context Dot find async find trip by using this trip ID and just return this so I guess we are good with all these methods so we have created get all add and edit and then get single so we are good with this cool save everything and let's move to the home page okay on home page let me remove this uh dummy heading here if you remember the demo I showed you we had one image there so it looks good that was the only purpose of that image so we'll add that image first so we'll use div class we'll use hundred percent of the width and opacity 75 this class also comes from bootstrap and in this div we will have an image IMG SRC and I already have this image which is Images slash travel underscore Beach Dot jpg cool and we'll add a class IMG fluid like this save everything and we should see this image now but before that let's work on the next thing that will then we'll run it once and check how the UI looks next we'll have a div with class container fluid container fluid and here we'll have m y 3 so vertically margin 3 on y-axis and P2 so we'll have some padding using P2 after this first we will have the heading recent trip and the add a trip button so for this we will have a div class we'll have a display Flex so deflex and justify content between so that we can see the recent trip heading and the add trip button at the corners left and right then vertically I need these two centers who are align items Center and then let's use hundred percent of the width inside this new first I am going to have H4 with class m0 so by default uh bootstrap adds some margin to all these headings but I don't want any margin in my case that's why I added this H4 class m0 so no margin and here we will say resent trips this will be at the very left and at the right we are going to have a button and we'll use label for this to give it the desired uh appearance what we want so we'll say label class we'll use a similar approach we used for the the bottom nav items bottom tab bar basically so we'll use this label here first we'll use busy light so the lighter version of the background text dark rounded pill to rounded corners no padding from all sides then from PX we will use two and from p y we will use 1. so on x axis on Y axis I am setting the the paddings after this we'll say margin 0 then display Flex and align items Center that's all what I need in this we'll head a plus icon so I class p x b X Plus this is coming from uh box icon then text dark to make it black then m0 P0 I don't need any margin padding after this we'll have the text so span and here also I'll add text dark and then the text is going to be add a trip save everything and let's try to run it and we'll see how it looks and we can see recent trips and add a trip button which looks nice pretty good but we cannot see the image and why so I have this image right so in triple W root collapse everything and we have image oh images this should be images like this save everything and let's rerun it's coming okay and we can see this image recent trips add a trip and it looks great do let me know in the comment so far how does it look is it looking great or no what do you think okay so we are good with this now now let's continue with the next part so after adding this tape now we'll start displaying the recent trips so for this first we need to have a collection here so we'll say private innumerable I enumerable of trip and we'll say underscore trips we will have a default value innumerable dot empty trip like this okay save now we'll use this underscore trips we'll populate the underscore trip the data in this on initialized async method now what we'll do we'll set trips equals we need to inject our trip service so we inject trips service so it should be trip service right let's have it like this only trips service and here we will say a weight trip service dot get trips async and page number one and the count let's have six underscore trips and now we can use this underscore tips we are getting the twitch data here but it's always a good idea to display the loader right so for this what we'll do we'll do the same thing we have done for uh first part what was the name of that app loader or no no tap loader we are using now interrupt directly or if you want to interrupt right okay let's inject my intro inject Maui interrupt let's call it Maui and here we'll say Maui Dot Maui Dot show loader and this get trip facing what does it written again it returns list of trips fine so we are setting the trips and after that we could say Maui dot height loader everything looks cool now now we'll use this underscore trips to display the drift data here okay so first we will check if strips has any item or no let's first work on the negation part so if we do not have any trip then we'll do something and if we have the trips data then we'll do something else so for the first case when we do not have any trip we'll simply display message so here we'll first create a div class let's call it empty trips container we'll add some CSS styling to this apart from this we'll use D Flex w 100 so for width and red blacks column so that two items uh should be displayed vertically after this we'll use a line item Center and justify content Center just if I contain Center tool let me minimize this oh let me stop it to work fast fine now we have this div and inside this div we will create move it like this fine Dave glass everything is fine right yeah in here first we have a label label class and it is again freaking out I don't know why if else Dev class we have this double quotes everything looks fine if I do this label everything is fine I don't know why it is not working uh okay so in this label we will display a message we'll say you haven't added any trape yet okay and the class will use text muted to make it uh kind of faded then we'll use a bigger font size fs4 then margin bottom we'll use mb2 and Y margin bottom because we are going to have another item here that item we'll use a button type button okay now the error is gone okay button type button and we'd add couple of classes here so we let class BTN BTN secondary and rounded fill cool inside this we will have one icon first so I class BX BX plus the same icon basically then m0 p 0 after this we'll have a span and we'll say the add a trip same thing basically save everything and now let's try it out run it it should display this box and we are here so we can see this cool it looks nice not nice because this is attached to the first part so what we can do let's consider this heading and this image it takes 50 of the screen although it is not taking 50 percent but let's consider it as 50 percent and then we can have the height on this empty trips container we can use b h 50. okay this class does not exist we'll go and create this class and we are going to use this on this page only so we can simply add a style tag Here style type text CSS and we'll make it scoped so that it gets applied to this one only vh50 and here we'll say height no we should not have height we should have mean height so we'll say VH mean 50. or maybe min vh50 main vh50 like this Min vh50 so we'll set Min height at 50 v h which is the viewport height so 50 percent of the viewport height we'll save it let's run and this time it should take the bigger space in the text should look in the center of that big I suppose let's see map is loading and we can see it and it looks nice cool let's try it out on Android emulator how it looks on Android run do we need to make any adjustment or it will look just fine let's see so on Android it looks here also it looks great right let's try it out these menu items trips settings save trip home everything looks fine so we are good okay let's continue first let's add the logic to display these trips then we'll work on the save trip page add a new trip or maybe we should work on this add new trip first right because then only we can see that repair okay okay so let's create a method here we will say private void go to add trip page and from here we'll use our navigation manager which I guess we have not injected so let's inject it inject navigation manager we'll call it navigation manager only and from here we'll say navigation manager Dot navigate to and we know what is the URL for our saved page main layout let me layout and we can see the URL URL is trips slash ad okay so we'll use this URL slash trips slash add and this time we don't need to set anything anything replace or something like that because we want user to come back if user presses the back button it should come back to this homepage only let's use this go to add trip page from this button on click and from the this recent trip and then from here also we have this label so from here also we'll do the same thing so we'll say on click and add this so save everything and let's run it it is on Android okay let's see it's so when we press that uh add a trip button from anywhere from both of these places it should navigate to the save trip page okay app is here let's try add a trip and we are on tripax manager this save trip page selected is also showing whom we'll fix this but we can at least see something and from this button also we are moving to the same way so things are working now now let's first okay let's continue working okay so let's move to save trip page before that let me close all these close all tabs now save trip page we'll start working on this page fine so first thing we need to have a model so let's say this is B of type trip model equals new default value and then in here first thing we will have that one background image so we'll use div class let's say IMG container okay and on this IMG container we'll add some CSS so style type text CSS and we'll add some styling to this and The Styling is going to be for the setting the background image so we'll say background image and we'll use the same image which we used in previous page the home page basically so that was Slash images slash travel underscore Beach dot jpg this image okay we'll reposition it so that it looks fine so for this we'll use background position y and we'll move it 100 pixel uh upward in up Direction fine this is IMG container and on this IMG container let's add couple of bootstrap classes so we'll say m0 P0 we don't need any margin any padding and width we need 100 VH so we'll say vh100 sorry not v h v w bits then for height we'll set a fixed height here and we'll use it somewhere 250 PX fine after this div we will start working on our edit form so added form and to this we need to pass a model and this is going to be our model and then we'll use data annotation validator to validate the peels hair and now after this we will use a div class let's say we'll call it a form container form container inside this we'll have one more div where we'll say div class from body and we'll use BG white we need it as white color we'll have some shadow then display Flags and the flex we want is column Flex column Flex direction is going to be column in this first thing we'll have a heading H3 on which we will add some classes and classes are going to be mt3 to get a margin from top and then text Center to move it to the center and here we'll say and a trip will make it Dynamic when we are editing a trip we will modify this thing but for now let's have it like this only after this H3 we will have the main body main content of the form so here we'll say Dave class here also we'll use mt3 and then we'll have one more div for the buttons so on this we'll say div class row and Y 3 so margin in y direction 3 so margin top and margin bottom three and in this we are going to have our buttons so we could use offsets but I'll do the very limit thing so what I'll do I'll say div class call one so it will take one column I'll simply skip this I will not add anything to this then I'll use div class call to in this I am going to use the cancel button so for that we'll say button type button and we'll add couple of classes BTN BTN outline Danger we'll add a shadow to it and in this we will simply have a icon and that is going to be BX hyphen X so that cross icon cool we have occupied three columns so one and two three columns after this we'll have one space so for that we'll use one column now we have used four columns next thing we'll use Call 7 for the main save button and then the last one we can skip this if we want but let's have it so now we have all 12 columns and in this 7 I'm going to have one more button which will be our submit button so button type submit we'll have some classes here so BTN BTN primary rounded pill and Shadow and here we'll say save trip like this save everything I want this section the footer section to be very uh and vertically so what we'll do in the center div the middle div we will add a class which is Flags grow one so what it mean it should take the all the available space in this Flex box so first we have added trip H3 it will take some space it will take whatever space it needs then the third div where we have all our buttons that is also going to take this piece whatever it requires and the center is whatever is remaining that we are assigning to this middle div where we are going to have our actual form okay so here we'll start adding our controls so div class mb3 version bottom three here first we will have a label class and we'll say form label first we'll add category trip category and here we will use input text but we'll use input type hidden we don't want to display it we don't want to show it we will simply use it just because for this category selection if you remember when I showed you the demo app in that we had the images and we could select any image so that was not input text or select box that was some Custom Design so we'll use that but whenever we will toggle the selection we will modify this input field this hidden field which we'll use to submit the form okay so on this type we'll say bind value and this value is going to be underscore model dot category image like this but now we need to have our category images so here we'll create a div with flags so display Flex wrap so that it uh perhaps to the second line if the content is not fitting into one row then it will add to the next row then justify content around to make the equal space between and around all these items now we need to show all our available category images so for that we need to have some State here we'll say private and then umerable or we could use array it's up to us so private will say what was the implication category Eddie and we'll call these let's say location categories only location cat there is equals array dot empty location category like this now we'll override our own initialized async method and first thing we'll display the loader so we need to inject our Maui intro and in this we will show the loader so show loader after this we will fill these categories but we have not created any uh would say any service for this so let's go to our services and we'll create a new service new class and let's call it drop down service drop or Downs service cool and in this we'll inject the same data context data database context sorry context like this underscore context underscore context and here we'll have a method so public async task location category array and here we'll say get location categories async like this and from here we are going to return underscore context dot get all async and this is going to be type of location category and we need to avoid it after that we'll simply say to array like this save everything and we have location categories now so let's first register this drop down service to our Maui program so we'll go here and we can have it also at single turn or transient it's up to us let's have it as transient save drop down service now we can use this drop down service owner save trip page so we'll inject this drop down service let's say drop downs and here underscore location categories we'll say a weight drop downs dot get location categories async after this we will simply hide the loader like this okay so everything looks fine now let's use this location categories array to display all these categories okay so here we'll add a for each Loop we'll say category in location categories underscore location categories and now we'll start adding the design and this design first we'll have a main div we will say div class rounded to make the rounded corners PS1 so padding start one will use a class v stack so this is vertical stack then we'll use text Center to make the category name to move to Center then we have a border border means it will add a simple border around this div and margin 1 from all the sides cool inside this we'll use First I class here we'll say position absolute and we'll use BX and then this is for that check mark if you remember so we'll display here BX check Circle and after this I we will display our image we will say IMG class we'll add couple of classes before that let's add SRC and this is going to be category dot image and the classes we'll use we say MX Auto to move it to the center and then let's say cat IMG category image let's say category IMG after this we will have a label class let's say category label and we'll display the category name here category name like this save everything let's see how it looks or maybe let's add other controls as well first then we'll check okay after this thing we'll use a validation message here and this is going to be 4 underscore model Dot category image after this we will add Dave Plus mb3 label class form label and here we'll say trip title or trip name input text with bind value as underscore model Dot title and we'll add couple of bootstrap classes first and the most pump control after this rounded pill and then let's have fs6 smaller font size and on this we'll use placeholder text so placeholder title or trip title trip title like this after this input text We'll add our validation message store Lambda and here we'll say underscore model Dot same title like this okay now let's copy this after trip name we will use trip location so it could be pretty State country or everything country this will be trip dot location model dot location and here we'll say trip location save everything fine after this we'll use one row in this we will use div class call so this is for column and in this column we'll use the same thing this is because we are using now we'll have trip start date and end date in the same row into different columns okay so we'll say trip start date and here this input text it would be input date point value will be start or whatever is the name Dot from date okay from date and this underscore model this should be from date only and trade start date start to date fine after this we'll do the same thing but inside a column so we'll say Dave class call to move it to the second column and let's paste the same thing he'll say trip start date we'll say trip and date model Dot to date right to date underscore model dot two date and trip and date save everything fine after this we will use the same div class mb3 and we have status trip status right so for this we'll say tray status and now we are going to have a show this status whole status we are going to have predefined statuses so we'll use input select here input select okay and in this first thing bind value it is going to be underscore model dot status now we have a problem this status if we check this is of type trip status enum but when we say this input select we are going to have the values as string so what we are going to do in here we will create a new property to manage that the display status basically okay so here what we'll do we'll create a new property public string we'll say display status right like this we added it here but we do not want this display status to be a part of our database model it should not go to the database okay we are going to use this only for UI purpose so we'll just display it so for this we need to add this ignore attribute what it will do whenever we are making database operation sqlite Operation it will simply skip this particular property so it will not try to save this in the database and it will not try to bind it from the database so that's all it will do so we are good with this display status now now but we need this display status to show on the UI and whenever we are changing the value from the UI so this display status is going to be changed not this status so for this what we can do this trip status this property we can modify this and we will make it as a full property and we'll add our own logic whenever we are setting or getting the value so for this we will first use underscore trip status underscore status with a default value of the script status Dot planned the same thing after this we'll change this to full property so public trip status status now we can simply comment this out we'll remove this in this forget we will simply return the status but for set when we are setting what we will do we will say display status equals value.2 string so whatever value we are setting and after that we'll set the Direct Value to this value so now what it is going to do whenever we are setting a new value to this status that value will automatically be set to this display status as well in string format so the name of the status in this case planned trip status just planned this enum value is going to be assigned to this status but the planned string this is going to be assigned to display structures now we can remove this thing cool so this is for uh when we are fetching the data from database it will be used for that particular thing cool now let's go here on this trip and date is fine start date is fine what they show them to date oh this should be input data input date fine so we have trip status here instead of add binding these two underscore model dot status what we'll do we will bind these two model dot display status display status let's add the message for display status only cool on this input select let's add classes same classes so we'll use form control and then rounded pill and then fs6 cool now inside this input select we need to add our list of status a list of available statuses so that we do not have so what we will do let's go to drop down service here we'll create a new method we will say public string array and here we'll say get trip statuses and these will get from NM dot get names and then we can provide the you know name type basically and the enum type is going to be trade status this type like this it returns string array so we will have string array in this now let's use this method on our save trip page before that we'll have one more state so private string array and here we'll say statuses and same thing array dot empty string like this and same thing will load these underscore statuses in this code status from drop down Service drop downs dot get get trip statuses this is not a async method we don't need to await it let's use this statuses so here we'll add a for each so for each word status in underscore statuses and here we'll simply use option with value as underscore status and the text as underscore status same thing save everything let's run it it's running in Android trip and we can see something but the design looks very bad so let's add the CSS styling for all these classes from container firm body category image category label for all these let's add styles so here we'll say from container then we have from body then we have category IMG right and then we have category label so we have these four things save everything non-form container we'll use background color as transparent we will use margin top as minus 200 PX why so so if you can see on IMG container we have height is 250 PX so we are moving this form container to minus 200 PX so we can see at least 50 percent of the image not 50 50 PX of the image at the top okay after this on this form container we will use some padding and that padding is going to be let's say 25 PX and 10 PX fine now let's move to firm body and on this firm body we will use background color as white after this we'll use border radius so we need rounded corners from left top and right top so what we'll do so 40px left of 40px right top zero left bottom zero right bottom we don't want any uh radius on the top on the bottom basically and then we will set a Min height on this and this mean height is going to be Kelsey so this is calculate function CSS calculate function we will say 100 VH hundred percent of the vertical height minus 200 PX after this we'll have some padding in this so let's say 15px from all the sides fine okay and after this for this category image we'll have a heightened width smaller height and width so we'll save weights 25 PX and high 25 PX so can category label let's use a small font size so font size 12 years save everything rerun and nice you see we have this rounded corner at a trip category trip name title everything location planned status start date and dates everything looks fine right cool next we need to work on the selection of these category image right now I am tapping on these nothing is happening so whenever I tap on on any of this it should somehow indicate that this particular category is selected right now okay so let me stop this for now and let's add some logic to make it selectable first we'll create a method here we'll say private void let's say toggle categories selection something like this and from here we'll pass the location category we will expect this category and now we will first check if underscore model Dot category image if this is already what we have in category image we are tapping on this if this is the same one we will reset it so we'll say model dot category image equals maybe null if that's not the case we will set model dot category image to this new category means like this single request and let's make it string dot empty to avoid layers fine now let's use this toggle category selection method on our images so we have this div in inner div so here we'll add on click and here we'll say toggle category selection and we will pass this complete category cool now this will work logic will work but the indication the UI visual indication should also be there so for this what we will do we will change this icon to filled icon and with color green and we'll add a shadow and border around this in color green so the selected category icon it should show that visual indicator so for this what we will do we will add some logic here that logic is going to be where I can class first we'll have default icon class which is going to be this BX check Circle which we already have and then we'll use text muted to make it uh faded like grade after this we will have border class so the default border we will have nothing after that we'll have the category name class so if it is not selected we will use text muted now we'll check if all this is selected how can we get this we can get this using model dot category image if this is equals to category dot image that means this current category is selected if this is selected we will simply modify these classes so first for this icon class we will use bxs solid icon so bxs check Circle after this we'll use text success to make it green then we have this border class border class we'll use border success border success to make it green and then we'll add a shadow to this then comes name class and here let's remove let's not have anything so it will be the default one which is text talk okay now let's use these classes so first icon class it should be here after position absolute and BX we'll say at the rate icon class okay then we have border class border glass is going to be applied on the first the top div so after M1 let's use border class border class and then on the name after this category label we'll say name class save everything and let's try to run it this time let's run it on iPhone run app is here let's tap on add a trip okay this is here now you see if we tap on any of this we can see this is in green color this shadow green border and this darker uh color of the category name right and if you tap on the same one if we selected on it we are typing the same one nothing is happening it should do the opposite right we have this logic if it was already this one underscore model dot category image equals equals category image it should be underscore model dot category image equals string dot empty and it is not working and why is it not working let's add a break point if we tap on the same one okay this came here and nothing happened if we select something else then something happens and why is it happening text muted these are the default classes right why is it happening uh let's try oh my bad so do let me know in the comment if you figure out what is the issue with this method just pause the video look at this method and check what is the issue with this method this particular toggle category selection and drop a comment and then uh resume it so that we can check that you got it or not okay all right so the problem is when we are tapping on the same thing again it comes here if condition matches it sets it string dot empty after this it comes out of this if Loop and then executes this line which is again setting it back to the current category image so we could say nothing has changed in that case but we will want this in else case so if this is the same thing we will uncheck it if this is not the same thing we have selected any other category then if we will use this save everything and let's rerun write out road trip Wildlife nature religious religious so it is working cool everything looks fine now next thing we'll work on this safe trip we should have some padding from bottom it is overlapping it okay we'll do this next but before that let's work on the save trip uh logic this method all right so for saving the trip let's create a method first we will say private async tasks save trip async in this first thing we'll show the loader my DOT show loader then let's add a try catch block and here we would say a weight trip service we need to inject our trip service inject trip service we'll call it trip service only and let's starts so trips service Dot saved replacing and we need to pass our model to this now this result if this is success and you're missing something new if this is Success we know everything worked fine we can simply display or that hide that loader and return back to the main home page navigation manager let's inject this one as well so we'll inject this inject navigation manager navigation manager so this is the approach I follow first a it must have this at the red page directive because this is a routable component routable page after that I use I usually add usings after that I use the if I have any Base Class so it inherits from some Base Class I'll do that after that I use implements if it is using any interface after that I inject the services which are provided by the framework by the Blazer only and after that I inject all the services which I created so in this case navigation manager this is provided by Blazer itself so I have it before and then at the end I have all these Services which I defined so this is the approach I use regularly okay so we have navigation manager and from this navigation manager we can simply navigate to in this case we will go to home page like this and we can remove this current page from the hierarchy so replace true this means if we press back so automatically when trip save it will redirect to home page and from home page if you press back it should not come to this page this is what it is doing fine if this was not success then we will display some error message so we'll say await Maui Dot show error alert async and the message we will use result dot error if we have some error message if we don't have any error message we can add some generic message that error while saving trip something like this okay and if there was some exception then also we will display the error alert should show error alert async and here we can say ex Dot message that's all and then we'll add a finally block where we'll hide the loader cool okay everything looks fine now let's when we are when we created this as strips retrievers saved successfully the our system it will navigate to the previous page but we should have some indication that the operation was successful the Traverse saved successfully one approach we could say show the success alert but using that user need to press that ok button but that is not what we want so in this case we will use a toast message so it will indicate that trip saved and that it will automatically uh be hidden automatically behind so for this we already uh added Maui Community toolkit we are going to use this so let's go to my introbe this class and here I'll create one more method public async task we will say show toast async okay show toast async when here we'll get a message like this and here we can make a toast so we'll say toast which will come from using Community toolkit dot Maui dot alerts dot make and here we can provide our message and then we can provide toast duration so here we can say toast duration dot short and then we can optionally provide a font size the text size but for now we will have it as default only after that we can simply call toast dot show method and this is an async method so we need to await it so we'll avoid toast dot show and if you don't want to do this in two lines we can directly remove this remove this variable and on this toast dot make we can directly call show method and because this is single line we can remove the body we'll use expression body method we'll add a weight and like this so toast dot make message toast duration dot short and Dot show now we can use this toast message when we are saving our trip so if this operation was successful we'll say a weight Maui dot show toast async here we can say trip saved save everything let's try to run it so first we install okay it is in iPhone only then let's run it okay we are here let's save trip and first let's fix this merge this padding issue so because this section the bottom tamper this is fixed we need to add some margin from uh padding from the bottom so what we'll do we will go to main layout.raser.css like this we have this padding top same way we'll add padding bottom and now the height of this we don't know if we can use this same height we are using for nav bar height so these are somewhat similar h e i g h t and we can add some additional amount let's say somewhere 20px save and let's return it should show this padding body content body content is the main container for body right so main layout body content yes tool let's see and yes we can see this right like this good so if we save trip directly we can see these error message validation messages so these fields are required we need to provide values let's do beach trip name some beach replication some which location start date and date and then trip status let's say ongoing save trip something happened no nothing is happening let's see what is the issue here so we'll go to save trip page after data annotation validator let's add a validation summary or maybe let's add this after all the controls in here save rerun maybe this is some validation error only Okay add trip select these things page some page some location and let's try to save trip still nothing okay let's try to add this breakpoint if you press save it is not going there that means there is some validation error for sure but what is the errors we have Melody validation message for display status validation message for to date for start date location title category image we have validation for all so what is remaining let's go to the stripe model we have ID title location category image here that's all what we need save trip page submit button okay let me check what is it is it related to status dot status save rerun I just said validation message to model dot status to check maybe if this error whatever error there is some error for sure some validation error only that's why it was not going to this map oh no oh my God this is a very silly mistake the mistake is I created this method but I have not used this safe trip facing now also it would not make any difference the point is I missed the save tree facing I need to call this from this edit form on valid submit on valid submit we should call this save tripacing save everything and rerun it should work this time let's add the data some big strips some location some random date planned safe and yes now it came here if I continue trip saved and it moved back to the home page and now we cannot see that message the text because now we have one trip in the data okay so now let's work on this recent trips section so let's move to home page stop debugging go to home page where is your home page here it is in this else part will start working first we'll have a container so Dave class row and we'll have some margin from top so let's say mt3 and in this we'll add a for each Loop where we'll say tray pin underscore trips and now we can start defining our main UI one by one all these trips so we'll have a div here div class call 6. we need it as two items on the screen in one row so call six bootstrap uses 12 column grid so if we say call six that means half of the screen okay inside this will have a card with margin bottom three and inside this first we'll have an image IMG SRC this we can get from trip dot category image trip dot category mystery dot category image after this we will have some classes on here so first we will say card IMG top this is coming from bootstrap only then IMG fluid after this we'll have one div with class card body card body and in this first we will have one H6 where we will display the uh trip title so the class will use bootstrap class card title then on this we'll truncate the text so we'll use text truncate if the text is longer we will truncate it and here we'll say trip dot title after H6 we'll have a P tag it will be card text let's use fs13 to font size 13 PX this class will be created if you remember text truncate will truncate text for this as well and here we will use trip dot location save everything and let's see how it looks so run okay this is how it looks and it looks great cool let's add one more this time let's say Island alone trip some Island location [Music] and save trip yes now we can see two items these two are looking great let's add one more this time mountains some adventure trip to the mountains save trip now we can see this as well so all these is looking great right okay fine now we'll work on the edit trip section so when we tap on this it should go to a separate trip page okay we'll work on edit trip later but let's first work on the single trip so this trip Details page okay so if we tap on any of this it should go to the trip detail page that's what will work next so let me stop it stop the debugging then we'll create one more page here so we'll say uh Pages add new dotted Maui not asp.net core razor component and here we could say single trip page create cool and on this first thing we need to have the URL of this page so we'll say trips slash and here we are going to have a trip ID which will be of type integer okay so this is the single trip page where we are going to display the complete details of a trip fine now this trip ID which we are getting as a part of URL we need to capture this so for this we will have a public property here of type int and the name should match the query string name for default case if you do not want this we have other approaches but for now most of the cases this should be in sync and will add parameter here so that it will be automatically supplied from the URL okay now we have trip we need to have the actual trip data so we'll use this underscore trip and now we'll override on initialized async in this let's make it async first we'll display loader and then we'll get the trip detail from our trip service so for that first let me inject Mao interrupt and then I'll inject our trips service trips service there should be trip service but I am using trip service from initially so I'm just keeping it going but it should be trip service that would make more sense okay here first thing we'll say Maui Dot show loader show loader after that we'll get this trip so we'll say await trip service dot get trip async and in here we need to pass trip ID okay and after this we will hide the loader fine like this save everything and now we will display that this trip details so for this first we'll have one image so we'll say Dave class container fluid first let's wrap everything in a condition where we'll say underscore trip is not null and that is because when it will come here async task on initialized async when it will hit this line number 22 it is going to render this text and if we use any property from underscore trip it will be object reference note set to an instance of an object that null object error no reference error so if we add this then it will only render the com details when this trip is not null so that means when we have data then only it should it will display this complete thing fine so container floor here we'll use m0 P0 no margin no padding at all in here we'll use IMG SRC and this SRC we are going to use trip dot category image and on this we'll use a class IMG fluid this class is from boot Step 2 make this image responsive cool after this we'll have a div to display the trip details here we'll say display Flex deflex justify content Center and width hundred percent so w 100 okay and then we'll have a class here let's say Dave class location low education okay it will be BG white so background color white we will have some Shadow on this we will use width 95 percent PX 3 so padding 3 from left and right and py2 so on Y axis we'll use P by 2 padding two and then inside this div we'll have one more div with class again D flux and justify content between so just if I content between an align items Center so I am going to have two things on each Corner left and right so on left corner we'll have an H3 where we'll display the trip title okay and then on the right side we'll use one span where we'll add some classes classes are going to be rounded pill foreign then px2 font size 12 and here we'll display the status so we'll say underscore trip dot display status save point after this will display other things so what other things first let's have a div glass v stack vertical stack here first we will display the actual location for that we'll use a label with class m0 no margin then px2 and py1 inside this first I'll have eye tag so I am going to display one icon here so BX map this is the icon and here we'll say m0 no margin and no padding P0 then we'll have some margin to the and end means right so to the right and that's because we are going to display the text after this icon so the text will display this will be span and here we'll say trip Dot underscore trip dot location location location like this save fine after this first level let's add one more label 4 start date and end date so for this the icon we are going to use is calendar BX hyphen calendar and then inside this class this span will say trip Dot prom date and we'll make it two short date string hyphen and then same underscore trip Dot to date dot two short date string like this tool after this we will have one more label and now we are going to display the total expenses for this particular trip so the icon we are going to use is going to money and then now we need to have total expenses which we do not have on this trip object right so for this let's try to have some expenses here hmm so first let's have a where is it here first let's have a private variable here so we'll say private double underscore total expense default value 0. let's use this total expense here so we'll say total expense Dot to string and we'll use the currency formatter so whatever currency our phone is using right now we'll show the expense in that particular currency only cool okay after this we are going to display the actual list of expenses right cool so let's okay we'll do both of the things together so after this we have this justify content Center this thing after image will start designing our expenses things so we'll say div class container fluid fluid like this and on this we'll say My3 and padding two from all the sides okay inside this first we will follow the same approach we followed on home page for showing that recent trip and add a trip button so we'll do the same thing here so let's copy that thing this div go back paste it here and here we'll say instead of do saying recent trip so we'll say expenses the expenses and instead of add a trip here we'll say add expense and go to add trip page we'll create a method here private void and here we'll say go to add expense page okay and here we'll say navigation manager we are not injecting it let's inject it so inject navigation manager navigation manager and let's use this navigation manager dot navigate to and from here we'll navigate to the add expense page save expense which I think we have not created yet that page we'll create it and in a moment but for till then we'll use trips after that we'll use trip ID so let me do this and here we'll say trip ID after that we'll say expense slash add like this okay expenses let's say expenses slash like this and we will not use replace true because we want user to come back to this screen if he presses the back button cool go to add expense page now let's modify change this on click to go to add expense page cool now when we have this total expense we need to have a list of expenses as well so that we can display those expenses on this page okay let's before that let's let's try it once how everything is looking app is here let's try uh okay we have created this page but we are not navigating to this page from home page fine so here on this call 6 let's add on click method and here we'll say let's create one more method private void go to trip go to single trip pages single trip page and we'll we can access trip ID here and from here we can say navigation manager dot navigate to and here we'll generate the same URL where we'll see trips slash the trip ID we got trip ID as a parameter to this method cool provide one click will say go to single trip page and we'll pass trip dot ID from here save everything uh it should be like this so whenever we are passing any parameter to the method we should use this Arrow function this Lambda expression function call run okay app is here now we can move to this page right alone trip some Island and now okay these things are looking nice but there is no way to go back if I was on Android then I have that back uh buttons from the emulator only together I don't know if you can see the those buttons so left in center and these three buttons here let's first create a trip so add a trip some Island location okay something is not right my screen is frozen or what okay screen is Frozen Let's okay okay so the point is I will check it on Android emulator later right now if you move to this single page we do not have any way to go back what we should do we should have a back button and we should change the title as well if you remember let me open it on iPhone only so if you see the title of this still says the title of previous page in our case it shows that homes title which is tripex manager the application name but this is not what we want in this case right it should display the pages header so like if you go to trip space then it shows trips this makes sense on settings it shows settings we are on home and then if we go here it shows this same Triplex manager this is not right so on this page we need to have a back button back icon and then this text it should also should be changed as per the current page so now how we are going to do this this backable button where we will have that back icon there should be there will be multiple Pages first we know the single trip page then second we will have the add a trip page this should also be with back button then from here from this ad expense this expense page as well it will also going to have a page from where we can go back and we can show that back icon so the way stat navigation stack Pages basically Works in Dot and Y in mobile devices this should work like this so the point is we are going to have two different layouts so one layout is this one which we have on home trips and settings page then we'll have one more layout which will be for all those inner pages so save trip detail save expense all these Pages we are going to have a different layout so let's work on that different layout it will be somewhat similar to this current layout with back button and on that page we are not going to show the bottom tab bars these two differences will be there okay and visual studio stop responding it again started to uh showing this Behavior okay now let's go to our shared folder here we'll create a new razor component so new file razor component and this will say let's say inner page layout inner Pages layout okay and on this page we can where did I created this inner page layout okay I created this in Services folder so let me delete this from here delete delete and add it in shared folder so shared new file eraser component inner pages layout create fine so we can copy everything we have on Main layout so I'm copying everything and pasting on inner page layout as well so we'll have this High disposable layout component based navigation manager app State Mouse interrupt everything looks fine the things we are going to change before this page title we will have one more section here which will show the back button the back icon basically so we'll have I recycle and here we will use the icons conditionally so we'll use this approach where we can check if Maui dot is Android if this is Android platform we have the icon BX left Arrow alt this is the icon left Arrow icon which will display on Android device if we are on iPhone's device iOS then we'll say bxs Chevron left like this and we'll make this a bit bigger so we'll use bxsm save now first we'll have this Arrow then we'll have this title after title we'll have this user Circle this also will make it Dynamic but for now let it be like this only after this we'll have this body and we can remove this bottom tab bar all together from this page we don't need this page we don't need this bottom taper on this page it is inner pages from where we can go back with backup button looks like everything is fine just this body content we had this class top neighbor body content bottom tablet light white right so we are using top never and body content on that play out also right so let's copy this first we could move these to app.css the main CSS that will be the right approach but for now I am using this type text CSS and I'm going to use it scoped so that these two things gets applied to this page only save fine after this this page title so we cannot use this page title now because this page title is for the main page title so now we need to have one more state where we'll say inner page title basically so for this let's go to our App State States App State this is the page title selected menu item so here we could have one property where we'll say public string string inner page title with get and private set and from here we'll say public void set inner page title set in your page title string page title we'll get this and from here we are going to get now we are going to set paste add inner paste item so we'll say inner page title equals page title like this now the thing is we need to we can use this inner page title you can see on this inner page layouts App State DOT inner page title now we need to do the same thing we are doing for this on initialized and dispose method we were subscribing to the changes in that particular thing in that we were subscribing to selected menu because those two were connected selected menu and paste title but in this case we only have inner page title so we need to have one more thing so if we do this route selected menu item changed then now next thing we'll have inner page title changed then we'll have the dynamic uh those Dynamic uh tab bar items for that we will need to add one more event handler so instead of doing all these what we can do we can simply use I notify property changed I notify property change this event using system dot component model we need to implement this interface so it gives us this property changed event and using this property changed event we can handle all these cases how we are going to handle these cases what we'll do for now let me comment this out this on selected menu item changed so I'll comment this out after this what we'll do we'll create a helper method here so private void let's say notify and here we'll use property name property name do we need this page name are we using this page name on here on the main layout main layout main layout on selected menu item change select image to test it okay we are not using that page name so we are good with this approach cool so we'll say notify property name and here will simply say property changed dot invoke and first sender is going to be this and new property changed event arguments property name like this we have this method Now notify and we'll use this notify method so from this set selected menu item we can notify with the name of which property we have changed we have changed selected menu item selected menu item this and from here in a paste title we changed this inner page title so one approach could be this calling this explicitly like this or we can make this also Dynamic how so when we are getting our setting at that time we can use full properties so for example if I need to show you with inner page title what we can do we can have private string inner page title with string dot empty default value so for this public inner page title from get we can directly return this inner page title but for this private set what we'll do first we will set value this underscore inner page title equals value so we are setting the value here after this we will notify with the name of this which is inner page title name of inner page title like this now we can say whenever we are saying this inner page title equals page title it is going to set it it will come here in this set method in this first it will set it after that it will call this notify so this is the same thing by calling this explicitly here so these two are same we can make it ah more we can make one more change here we can say caller name we will say not Caller Name color member name okay for this we need to make it we need to have default value so now what we can do from this notify we can skip this thing so we'll simply say notify and it would automatically get the scholar member name who is calling this notify winner page title we're calling this name uh this notify method in this case so it will automatically be set but from here on line number 34 we need to explicitly call this pass this because we are calling this notify in this case from this set selected menu item so this property name would set to set selected menu item if we do not pass this but that's not the case we want to modify the selected menu item we know we need to notify the property changed for this selected menu item thing so we are doing this so in this class I am going to leave this like this only both of these approaches but you could simplify this and for the selected menu item also you could use the same approach with this full property and notifying like this cool now what we'll do we'll change the selected menu item change thing and if you want to use the hybrid solution both of these so for selected menu item you need to you want to use this explicit event for all others you need to you you want to use on I notify properties that is also fine everything will work both of these approaches will work uh single-handedly or both with each other also so it's up to you how you are uh uh implementing it in your solution cool now we'll go to main layout first to fix this thing right so selected menu item now this is not defined but we have property changed same thing here we'll say property change now the type is not this so object sender is fine but the second item this is property changed event args so this is this thing property changed event as and which will be coming from from where system dot component model so we'll add a using here using system dot component model like this save everything and now we'll have property changed event arcs let's say e only and now we are good the only problem is now we are using this poor property changed and this property change this event is going to be triggered if we set this inner page title as well but if we are setting inner page title then there is no point of having this one main layout or maybe we'll have other properties as well for this notify logic so we don't want all of this instead what we'll do we can do first let's change the name of this own selected menu item change to on property changed or let's say on selective menu item changed only no we should change it because we are going to use this for tab bar item change as well so what we will do we'll say on App State property change let's use this this makes more sense rename all these fine and now we'll change this expression body to full and here what we will do we will check if e Dot property name if this is same as name of App State DOT selected menu item then only we'll say call this state has changed so now it will be subscribed to this property change but this state has changed will only trigger when we are actually changing the selected menu item property okay cool so let's copy all these things on initialized on App State Property changed and disposed go to Inner page layout and we'll do this same thing on this page we'll simply change something and that something is going to be instead of selected menu item in this case we'll say inner page title if inner page title is changed then we'll call state has changed and we need to inject nor inject we need to add using system dot component model like this and we are good now we can see on apps now first thing let's remove these cool we don't need this map or this is home selected trip selector because we don't have all of these on this enter page layout cool everything looks fine okay let's continue and what we are going to do next is we will set this inner page title the same way we are setting the main page title right so on this single trip page what we will do first we'll inject our App State inject App State App State and on initialized async method here we'll say App State DOT set inner paste item and we are on the single trip page so here let's move it to after trip we have trip then we'll say underscore trip Dot title so we'll set like this save find single trip page and 4 the save trip page this is also an inner page so on this when we are on on initialized async we'll say Upstate dot set okay we need to inject this App State we'll say inject App State App State and we'll say App State DOT set inner page title and here we'll say add a trip save everything now on this save trip page we need to tell Blazer we need to tell that this is not going to use the default main layout main layout is default we need to tell it that you should use the layout inner Pages layout this layout so we don't need to add this for in the case of main layout that is default inbuilt if we are if we want to change the layout then we need to explicitly Define at the rate layout and the layout name we'll do the same thing on single trip page so let's go to the top and here we'll set this layout like this save let me save everything top debugging okay and then one more thing we'll do but put before that let's try it out how it looks then we'll work on that go button that go back button basically app is here let's go to single trip page we can see the title and the back button this is the back button right which looks fine hmm okay right now this back button is not working we need to work on this back button now the thing is in this case the single trip page we have the single trip page we have set inner Pages layout this back button exists on the layout and this layout will be used for multiple pages so how would we know that what is the previous page if we are coming from home page if we tap on some trip it will go to single trip page in this case the back previous page is home page if we are coming from trip space on that page we are going to display all the trips we'll tap on the trip it will navigate to this single trip page and now if we press back button or if we add if we click on that back button now it should go back to the trips page not home page so the inbuilt navigation manager which Blazer gives sets it does not have the history features it cannot uh store the history hierarchy whatever Pages we have navigated so this feature is not available yet we need to do some work around to get it working to record to maintain the history of pages we navigated from here and there so for that what we are going to do there could be one approach where we can have a class with navigation manager we'll have some static list and we will simply keep on adding or removing items from that particular list so let's say we are a home page by default it will have single home page then if we tapped on this trip space the single trip page we will add the single tip to that collection and then if we press the add expense button then it we will add one new entry to this so this is how we can get we can maintain a history but in this case I am going to use a different approach the approach I am going to do so if you remember I told you earlier that we are not going to use nav Link in this complete app we are using nav link component on the sign in and sign up Pages only because there we don't want to make any history we don't need to maintain any history navigation history but apart from that we need to maintain some history that's why we are always using the navigation manager to navigate around and that's why I am having all the navigations using this methods so go to editor page go to single trip page I could have written this line directly in the template but that is not what I have done why because using these things we can track that on which page we are going do we need to have some reference to the previous page okay so I think this is uh becoming complex but when we'll implement it it will not let complicated it will it is a very easy actually so the thing is when we are directly moving to some page from where we are allowing this back button then we will simply add one history state that we have back page we have previous page for this one so for that what we are going to do first thing let's stop it we'll create a new folder and we will implement this navigation thing using an extension method we will create an extension method so first We'll add a new folder where will this will say extensions and in this we'll create a new class which we'll say navigation manager extensions like this okay so on this navigation manager extensions I am going to have the complete uh navigation related logic Pages Services resource States utilities okay in this first because we are going to use this for extension methods we need to make it static after this in this what we are going to have we will have two methods first public static void we'll say go to inner page when we say go to Inner page that means the page which has that inner Pages layout and we have back button that is we are going to call Inner page so we'll say go to Inner page and we'll use this dot navigation manager navigation manager navigation manager navigation manager like this and then we'll have the inner page URL inner page URL okay from here what we'll do we'll say navigation manager dot navigate to this inner page URL navigate to this inner page URL so far so good but in this case we will add an extra information extra piece of information which will be this new navigation options we can pass this navigation options to this and in this we have these three things Force load that means uh this is not going to be a Blazer client side navigation it will be complete page refresh so it will uh download it will load the complete Blazer app from the scratch that is not what we are going to use then we have history interested that we are going to use in this and the third one is replace history entry this is what we keep on seeing from sign in sign up pages also that replace that parameter so replace means this current page is going to be removed from the stack so we will go to the next page but we will actually replace the current page with the new page and when we press back button it will not come to the current page because this page Now does not exist cool enough talking let's use this history entry State this is actually a nullable string so we can add any additional state to this in this case we will set the current page URL to this okay so that we can come back to this current page now how can we get the history entry State here the current page URL for this let's create one more extension method so we'll say public static string and we'll say get current page URL this navigation manager navigation manager okay and from here first we'll say navigation manager Dot we have this URI which we have the complete URL so the domain slash ABCD digital hdf whatever it is on this what we'll do we'll replace something and that something is going to be navigation manager dot base URI so this is going to be the first part of the URL so first protocol HTTP https then the domain input that is going to be base URI so this means if let's say I am on the uh save trip page so how the URL is going to look like it will be something http 0.0.0.0 slash trips slash add something like this right this is the navigation manager dot URI this is this now if I say navigation manager dot base URI in this case this will be HTTP then till this zero zero I don't remember if it adds this slash or no I'm not sure so in this case when we say get current page URL what do we want we want this slash scripts slash ad that is all what we want right so if we use this when we say get current page URL it is going to return us slash trips slash at slash trips slash add this this is what we want in this case so we'll replace base URI with nothing empty State okay then we don't know if we have the slash or not so what we'll do we'll say trim start if it has we'll remove this and we'll add the slash manually at the very beginning like this so now we are handling all the cases if it had slash then we'll simply trim that and we'll add our own if it did not have then trim start will not have any effect and then we'll add our slash so this is fine this is the current page URL now we can use this here so navigation manager dot get current page URL like this this is go to Inner page now we'll have go to back page so we will say go back public static void go back this navigation manager navigation manager navigation manager and from here we are going to go to the back page now two things here let's have a fallback URL if we don't have anything in this state then we'll use that fallback URL so we'll say fallback URL and we'll have a default value for this slash or let's say slash home okay now what we'll do we will navigate but before that let's check the back URL so previous page URL or something like this previous page URL okay this we are going to get from navigation manager Dot history entry state if this does not exist or this is null we'll use this fallback URL now we have previous page URL we can directly use this approach navigation manager dot navigate to and we'll use this previous page URL and in this case we'll set this navigation this history entry state to null hmm and in this case we'll set replace entry state to true because we don't want user to come back to this page if we if user presses the back buttons we are actually replacing this current page with the previous page cool so we have these extensions now let's add these uh this name is Page to our underscore imports.racer so that we can use this on our page on all our razor pages save fine okay now we can go to Inner page layout and here we have this back button this one I so here we can define a method where we'll say private void go back like this and from here we can say navigation manager Dot go back like this this go back method what we Define we just defined go back we'll call this on this I so we'll say on click call this go back method cool so go back is what going to work from here but now we need to change our methods all those navigation methods to this go to Inner page call right so for that first let me close all the pages close all tabs now we'll go one by one first we have our home page from home page we are going to go to add trip page so this is going to be an inner page for sure so we'll say navigation manager Dot go to Inner page then go to single trip page this is also going to be a inner page so we'll say go to Inner page and on here we are going to have go to add trip page okay on home page I think this is all what we have after home page on index we don't have anything on Save trip page we had that cancel button this button we need to go back from this button but before that save trip save trip do we have any navigation here yes we have navigation manager dot navigate to home but in this case we are not directly going to home what we'll do we'll say go back so whatever previous page was here it will go back to that page and we have any other navigation manager called no we don't have any other on this button this one will add one click and here we can directly call navigation manager dot go back like this like this so we are going to go back from here what is the error okay this is in false alarm cool safe trip is fine now let's check another page settings we don't have anything sign in sign up we are not going to use these for this uh this logic then we have single trip page winner Pages layout what is the issue within your page layout okay we'll check go to expense page this is also going to be a inner page so we'll say go to Inner page like this okay looks like everything is fine now on trips page we do not have anything cool so let me save everything and let's run it it is running on iPhone let's see now the back Behavior those back buttons on the top that should work okay now first let's try I am on trip space and I am tapping this plus icon now I am on add a trip page now we cannot see that bottom Tapper which which is fine because now it's we can be sure that this is inner page we have this back button if you press back button it should go back to trip space not home page it came to home page looks like there is some issue from this plus page on our okay that is going to be on Main layout cool this go to winner page okay we missed these calls let me stop it so go to pages that is fine navigate to but when we say go to Inner page we'll use go to Inner page like this let's run it again and try it out okay let's try the same thing now I am on trips page and I press this plus button I am on add a trip page back now I am in trips page now go to home page go to edit trip page if I go back now I am on home page that means this functionality is working now let's say I am on the The Strip page single trip page I came from home if I press back button I am on home same thing let's go to add expense okay I have not created this page but you got the idea these things are working as we expected let's try the same thing on Android stop Android emulator let's run it okay we are here I'm on trips page nothing will happen I go to this from here if I press back button I am on trip space I'll go to home page add a trip page I have this back button if I press it I am on home price home page so this functionality is working here okay let's stop and let's continue so before this where were we yeah we were at the place where we wanted to add our expenses cool we were on single trip page so from here we have this total expenses and somehow we need to calculate these total expenses for this complete trip and we need to get the list of expenses as well so that we can display those here now instead of having these separate collection what we can do we can go to the strip class and here what we'll do we'll say public we'll create a property basically so we'll say we'll add a public property so private enumerable of expense and we'll say expenses like this and we'll add ignore to this one as well now we need to get these expenses so on single trip page there is no point of having a separate call instead what we'll do we'll go to trips service Al when we are getting a single trip so get trip async to this we will expect accept an additional parameter where we'll say include expenses and the default value we'll use false here what we will do we'll first safe trip in a variable then we'll check if include expenses is true now we'll patch all the expenses so we'll say a weight context Dot get filtered async what we need expense and the filter condition is going to be expense dot trip ID equals equals this trip ID all the expenses for this trip like this so now this expenses is an innumerable of expense and from here we can set trip dot expenses equals this expenses or we can omit this variable directly by using this thing directly here like this okay and we can have a default value if we don't did not get any expense then we could say enumerable dot empty expense like this and then after this if condition we will return trip now what will happen if we did not pass this or this is false it will simply fetch the trip return the trip the same old Behavior now if we pass this include expenses true then it will first fetch the trip then it will check okay we need to fetch expenses as well then it will simply fetch the expenses from the database for this particular trip you can add it to this trip dot expenses property which we can use on our UI cool let's go to single trip page for total expense after getting this trip we will set this total expense to underscore trip Dot expenses dot sum and we'll say a DOT amount we are calculating the sum of all the amounts of all the expenses for this particular trip this is what we want right and when we are fetching the trip after trip ID we'll pass the second Boolean parameter include expenses in this case we want it to include the expenses so we'll say yes include the expenses so it should be true cool so we have total expense logic after this we will work on displaying the list of expenses if we have okay so in this after this add expense button this display Flex here we'll first check if underscore trip dot expenses dot any if we do not have any expense then we'll display the message the same way we are displaying on the main home page for recent trips and then we will have an else condition where we are going to display the actual list of expenses when we have those settings cool so when we don't have any expense we'll have a div or maybe let's go to the home page and let's copy this section where we did not have any trip let's copy that section go here like this now Min vh50 we are not going to have this because this time on this page we have other items as well so we cannot use we should not use main Min vh50 we should use some smaller height so on this we can directly add a style tag we'll say main height something like maybe 200 pixel that is fine you haven't already added any expense yet and here we'll say add a trip instead of add a trip we'll say add expense expense and instead of go to add a trip page we'll say go to add expense page cool now let's work on the other part as well then we'll uh go and check that or maybe okay first we need to define the save explain space right cool so let's first see this how it looks I'm running it on Pixel Android okay app is loading add a trip look it was not working right the dates were not working at that time now it is working okay so we have Beach from Beach some beach location trip start date once let's use anything planned we can use ongoing save trip we can see this okay this uh the toast messy was also there some beach we are here and we can see this ad expense and this ad expense you haven't added any expense yet and if you press this add expense it is going to go to the express page which we have not created yet we are going to create in a moment okay but before that let's work on this section Also let's add the rounded Corners to this so this is on single trip page we have this VG white shadow this location right this is the same thing okay here if we directly surrounded let's rerun it on iPhone app is here let's try it out and yes there is this rounded corner but this it is very less so let's do one thing we have this location class we'll add a CSS to this so on this page we'll say style type text CSS it should be scoped and here we'll say location and we'll use border radius as [Music] um 20px like this and on this sum Beach trivia knot it should show that status also right but it is not showing that status and that is because we have display status we should see this display status okay we have this text white it should not be text wide text docs let's rerun app is here we tap on it and now we can see this cool so we can see this plant we should have some background color some beige planned total expense 0.00 date time location everything looks fine just this plant this should be in some uh background and that background we are going to use some Dynamic Logic on the basis of the status so what we'll do let's have something here only so we'll say where status color and here we could say trip dot status we'll apply switch on this so switch we'll say trip status dot if this is planned we will use BG secondary this is not it started that means if we have ongoing for this we'll say BG success if this is completed trip status dot completed okay spelling is incorrect will fix this BG hyphen let's say primary and the last one we have tripstatus dot canceled if it was canceled we'll use BG Danger and then we'll use this status color on the this thing will use status color class and then we can use text White so we'll display the textures white color for all these cool there will not there should not be any other status that's why it is complaining but we know there will not be but still we can use in that case BG dark this will never come but still we can have it okay so looks like everything is fine let's rerun app is here app is speech planned grayish color a long trip planned this also planned did I use the same thing let's create a new one Hills page some hail area some random dates and the status let's use ongoing save trip go there and this is still planned which should be it should not be planned it should be the ongoing in this case right so something is not right if we go to our trip surveys okay I got it what is the issue so you can pause the video and do let me know in the comment if you figured it out what the issue is if not I'm going to tell you so the problem here is if we go to trip class here we have these two things display status and this status so we are setting the display status whenever we are setting the status that means when we are getting data from the database at that time we are setting this status so we are setting the display status but there is no logic to do the opposite of this so we are using display status on the UI for this input select that drop down and when we are trying to save the data at that time we are not setting the status value so it is always getting this default value trip status dot planned that is why it was showing this so what we should do there could be multiple approaches the easiest approach will be here when we are saving a trip we could say trip dot status equals here we are going to pass we'll say NM dot parse we should use triparts but I am going to use Parts because I know this values always be valid value so here we'll say NM dot parse and the type of the we can have the this also right yes tenum so it should be trip status this enum and the value is going to be trip dot display status like this we are setting the actual status in let's try it out stop and let's run okay app is here now all previous ones will use the plan only because that is what they have saved this road trip let's use road trip City nodes some date and the status let's say completed save trip and this road trip and now we can see completed right the text is changed and this the background color is also changed that means the logic this status color logic this is also working fine cool next thing we'll work on the save expense page okay so for this what we will do in Pages we'll create a new file dot net not.net mobile asp.net for Razer component and this thing we'll call Save expense page okay and on this we'll use page then the URL we had trips trip ID which will be of type in then slash expenses slash add save and in this we need to capture the strip ID so we'll create a public property of type in to we'll call it trip ID and we'll decorate it with parameter so it will be passed from the URL cool save everything now on this save expense page and save trip page both of these are going to share the same layout okay and when I say same layout so this form container form body this main layout interface layout this is fine this is going to be same but apart from this uh this thing form container firm body and this this section only then heading is going to be changed and the action of the button is going to be changed in this case it will save the trip and on expensive page it will save the expenses okay so the point is we could create a separate component shared component and then we can use that component on both of these Pages for this broad this main outline basically so we'll create a new razor component let's create it in shared folder so in shared new razor component and we could say form content on this let's go to save trip page and start getting the content so here we'll say first we'll get this content add a trip div class mt3 Flex grow one till this Flex grow one so copy this thing go to uh from content paste everything after this we'll get the bottom part as well so this thing we don't need this validation summary now we can remove this and in this after this we'll get this data so after this we let this thing cool go back we need to have this go back method okay this will be direct so we can inject this navigation manager here so inject navigation manager save now there is some error with this what is the error this tab okay we are missing the main div this div is this after this we'll have one more div this thing now everything looks fine now the thing is we will have the dynamic content here in this Flex group one the main form components form controls are going to be placed inside this div so on Save trip we already have all those controls but on Save expand space We'll add those so the point is this is going to be a dynamic set of HTML content so for this what we'll do in our code block we are going to add a property which will be of type render fragment and the name we'll use child content so this name must be child content because this is how Blazer uses the child content the direct content inside that custom controls custom components we can directly add content and that will be mapped to this child content and for this also we need to set parameter and then we can use this child content directly as a child of this flax grow one like this here save everything and now we are good next thing this add a trip this should be dynamic so we are going to get this also as a parameter so we'll create a property here so prop type of string and we'll say heading and this will be parameter and we are going to add editor required here this editor required uh how this works it will show a display warning on the page when we are calling this component so it will tell us that you are missing heading which is required for this it will not error out but it will show a warning so that with the developer the consumer of this component can know that we need to pass this we must pass this and I'll use this for child content as well after this one more thing we have this save trip this button text so we'll get this button text as well as a property so public string button text like this so parameter and then editor required fine so we'll change this save trip to button text like this and this add a trip will change this to heading heading like this cool so now we have this component ready form content now we can use this form content first let's try to add this on Save drift page and then we'll follow the same approach for second one so here we'll save form content now just check I am doing this save now it is showing something and I don't know it is not showing the actual warning it should show on Windows it shows or maybe let me try one thing let me close with visual studio and open and now it is showing this nice little animation so you will see this Red Line comes then goes then this form content the color changes for this so this is because it is just trying to figure out if this component actually exists in our project if this is a valid component or not that's why it is showing this it is not able to figure out but trust me we need to add edit required for required uh properties required parameters for that particular component fine what we'll do here on form component first we need to provide heading so for this heading we know we need to pass add a trip this is the heading after this add a trip we need to provide button text which will be save trip and then we need to provide body and then body that body is going to be this child of this mt3 Flex Groove one so let me copy everything inside this [Music] um till this status copy and add this inside this then we can comment this out directly okay now let's see if it looks same as it was looking before and if it is working same as it was working before let's try it out uh there is one more thing this form container and firm body these two classes these do not belong to this component now save trip page these belongs to form content form container and form body so for this we'll add a style tag Here style type text CSS will make it scoped so that it gets applied to this component only form container and let's try it out run it is in iPhone let's try where is it app is here let's try it out go back and add a trip page so it looks same if we tap on Save trip it shows same this the category image field is required it should be left aligned only let's fix this and this save trip it should take the complete space so let's fix these two things so for this button what we can do we can wrap this button this button inside a tab with class D grid which is display grid inside this there is only one content which is going to take the complete bit and the second thing was this thing child content we need to move the text to left so what we'll do we'll wrap this child content in a div and text start and we add child content here let's let's see now restart it's it's here let's try Plus and everything looks same save trip page and this category image field does not go left okay let's we'll do some okay I got it it is coming from this D Flex here we have D Flex justify content around this category this one this justify content around right so what we can do we can simply move this out of this div so in this case it will be left aligned okay fine we are good with this one now let's work on this add expenses page now if we click on ADD expense we cannot see anything the because this is using the default layout we don't have anything on the page and this is using default layout so let's fix this first we'll set layout as inner Pages layout and in the override override on initialized async what we'll do we'll simply set the title so we'll inject App State we'll call it abstract only and here we'll say Upstate dot set interface title this will be add expense add expense save everything and let's rerun I missed semicolon let's add it and rerun okay it should be a sync fine cool let's go to the page at expense now we can see ad expense so this is we cannot see that bottom tab bar that is fine the add expense this is changed we have back button so this is working fine now cool now let's add the form actual form to this add expense page for this let's go to save trip page first let's remove the commented code uh this one we don't need this section now remove this fine and let's copy everything on this page just leave the strips add apart from this let's copy everything go to save expenses page and paste it here let's make some adjustments first thing instead of add a trip it will be add expense the page title after this IMG container this image instead of using this Images slash travel Beach image we'll use a different image which we have which is money.jpg okay after this next thing what will change we will change the type of model this is going to be expense and on this we are getting this trip ID so let's add parameter here to capture this trip ID so we'll say Pro public int trip ID add parameter attribute cool we have this trip ID now in this we will have a list of categories expense categories so we are not going to have this remove this private string array here we'll say expense categories expense categories in on initialized async we have set inner page title add expense loader then let's remove this thing remove this thing as well in our drop down service in our various drop down service here in this let's create a new method public async task string ready and here we'll say get expense categories async and from here we'll fetch the all the expense categories so context dot get all async expense category like this and on this await we are going to add a select statement where we'll say e dot name this is the expense category name dot two array um so now we have string array for expense categories this we can get owners save expenses page so here we'll say underscore expense categories equals a weight drop downs dot get expense categories async tool toggle category selection this does not apply to this one and this method it should be save expensesync save expense async and here instead of trip service dot save tree facing we should have save expenses which method does not exist right now so let's go and create that method so we have two approaches either we can have this in trip service or we can create a new service for all the expense related stuff but because experience is tightly coupled with trip because expense is required trip ID so I am going to have this in trip service only but you are free to create your own service for expense cool so here we will say public async task method data result of type expense we'll say save expense async and we'll expect a parameter of type expense and let me copy this logic which we have in save tripacync in here we don't need this status setting and here we'll say if expense dot ID equals 0 we are creating adding a new expense so we are adding expense or add expense or here in the else case we'll say modify an existing expense which will do in a moment here we'll say expense and the model is going to be expense repeat same thing here expense expense and success expense and ex Dot message this should be of type expense like this this should also be of type expense so save expense async method is ready and now we can use it here so here we'll say trip service dot save expense async and we can pass this model directly and we'll delete this section we don't need it now instead of paying trip saved we will say expense saved and we'll go back error while saving expense and I think this method is done save expensesync let's add it to the own valid submit save expensesync now let's add the form content main form content so here what we'll do let's copy one of this and delete everything inside this form content now we'll start adding the data but before that form content heading it should be add expense button text should be save expense and the body we are providing the body now this thing we'll see first thing is the expense titled or name so we'll save for what so model dot four here we'll say forward placeholder and this is going to be 4 like this looks fine cool let me copy this thing now paste it again this time we will say how much and this is going to be for amount amount and instead of input text we'll say input number placeholder would be how much like this then next control this will be the category expense category basically so here we will say category and instead of having input text we'll use input select input select and will bind value with underscore model dot category we'll add classes so form control Plus equals form control rounded pill and fs6 same classes in here we'll add a for each before this four reach We'll add a default option so here we'll say option value blank and here we'll say select or choose category choose category and in this four each we'll save our category in underscore expense categories like this here we'll add an option option value is going to be the same category name and the text is also going to be the same category like this and this validation message is going to feel underscore model dot category fine after this let me add one more four the last part which is when so when and it is going to be input date input date and bind value is going to be model Dot spent on and we'll do same thing here and the placeholder will change it to spend twin save everything and looks like everything is done on this page okay let's let's quickly try it out how it looks okay let's go add expense and now we can see everything right we can see at experience header background image for what how much choose category all these are the categories we can save expense with the values we should change this this error message how much right so forward how much on when it will open up the calendar everything looks fine let's fix this message how much so for this we need to go to expense uh expense model and here we have this range here we'll say error message with please enter valid amount that's all stop run and let's say okay we'll go here at expense and please enter valid amount this is here cool search looks fine we can yeah did you check if we can we press on this cancel button it is navigating us to the back page because we added that navigation manager dot back and this thing is working fine next let's save this expense and populate expense on this trip trip Details page okay now let's work on displaying the expenses on single trip page let's fix this please there there is spelling mistake right we not spelling which the casing we're seeing not consistence please enter valid amount this is fine now let's go to single trip page here we have this if condition if we do not have any expense for this particular uh trip then we will display this thing that you haven't added any expense yet and add Express button if we have the expenses for this particular trip then we'll show those so for this what we will do first we will have a div class row with margin top 3 and in this we are going to add a 4 each Loop here we'll say where expands in underscore trip dot expenses and then we'll work on this here we'll use the complete screen so we'll use div class called 12. complete grid complete width and now we'll start adding the main parts so div class card with m y 2 and P3 super margin of 2 and padding of 3 inside this we'll add a div with class D Flex so display Flex and then justify content Center and align item Center align items Center and inside this div we are going to have one v stack and in this v stack vertical stack first we'll have an H4 where we are going to display expense dot four so the expense description basically the expense name after this we'll add a span inside this H4 only we'll display the badge and so here we'll add classes badge and BG primary and this span will display expense dot category here okay after this H4 we will have a label and inside this label we will have I class will add an icon calendar calendar icon basically and then with some margin me2 and here we will display the date when this expense was made so we'll say expense dot spent on and this is nullable so we'll use question mark Dot two short date string okay after this will come out of B stack this v stack and here we will display one H3 tag and inside this we'll say expense Dot amount with two string as C which is for currency and this should not be just by content Center it should be justified content between so that these two things show side by side okay looks like this is fine okay let's try it out so I'm going to run it on iPhone it's here let's try it out we are in here add expense save expense and we have these errors forward something gibberish then 10 choose category food when any date and save expense and we can see expense saved but we cannot see any data here we should see some data right so for this we might be missing something we set trip service get trip async we are passing the trip ID um yeah it looks fine from here when we are setting this okay so we are missing one thing and that one thing is we need to set the trip ID to this model right now it might took 0 default value because we did not set it so we'll say when we are coming this uninitialized racing after hiding load after doing everything we'll say model dot trip ID equals trip ID this was the missing piece let's retry rerun okay let's go to this again add expense something choose category fuel some date save and yes you see now we can see this one expense here and this got displayed here and we can see this total expense amount to be 23 which is the same let's try adding one more some food 12.34 some random thing and food then some date save expense and now this total is 35.34 dollar and now we can see two entries uh the text 4 then category and then amount so this thing is also working cool now next thing we'll work on if we tap on this uh this card where we are displaying this expense so we need it to redirect to edit expense page so we will have added expense feature as well for this let's start working so here for editing an existing expense we are going to use this same page so for that we need to have a different URL so we'll add one more page so we'll set trips trip ID expenses and after this we'll have expense ID which will be long and then edit okay so now we have this expense ID in the URL we need to capture this so we'll create a property here public long and we'll use expense ID like this and this should be marked with parameter attribute and this is going to be nullable because in the first case when we are opening this form for creating a new expense adding a new expense then we do not have this expense ID so it will be null in that case so we'll make it nullable now if we had expense ID we should load this expense details on the basis of this expense ID and then we'll modify this underscore model at that time this should be the modified model so here what we will do after loading the categories we'll say we'll check if expense ID had some value and that value is greater than 0. like this if this is the case we'll say model equals a weight trip service Dot get expense async that method does not exist so we'll create that method so let's go to trip service here we'll create that method so that is going to be public async task of expense will say get expense async and we will have expense ID as a parameter and from here we'll say a weight context dot find async expense with this expense ID okay this should be nullable that returns in a label but it should never be null in our case but that is fine so get expense async we'll use this trip service dot get expense async like this okay this might be some false alarm okay if we have this model everything looks fine after this we will hide the loader and set the strip ID to the current trip ID okay get expense ID we should pass the expense ID to this expense ID this one like expense ID dot value because this is long cool we have this model now for edit for editing case now this add expense does not make sense this inner page title right this should be changed in this case what it should be it should be on the basis of this condition same uh what is the button text save expense so button text is fine we just need to change this heading okay so what we are going to do we have to two approaches maybe we can add this set inner page title we'll say this was add expense so this will be default in the else case where we are saying that this is the new expense and if this is not the case in this first if condition we'll say edit expense like this I guess everything should do work now and we should be able to modify an existing expense cool now let's go to this page whenever we are tapping on this expense card so I mean single trip page now on this call 12. here I'll add on click method and here we'll say let's say go to edit expense page something like this thank you like this go to x edit expense page we need to pass expense dot ID to this method let's create this method so here we'll say private avoid go to expense long expense ID and here we'll say navigation manager dot go to this should be inner page to this one so go to Inner page and now we are going to generate that complete URL which is this one trip strip ID expense expense ID and then edit so here we'll say that we paste this we will have trip ID then we'll have expense ID which we got as a parameter to this and then add it so okay I think all the pieces are done now in this case let's run it so add expense and added expense both of these should work now okay let's try some beach we had this expense some food okay edit expense and we need to change this heading as well add expense right right let's do this so on Save expense page this heading is coming from this heading so we need this same thing for both of these cases right so we need this here as well so what we can do we can have a private variable here so we'll say private string and let's say title default value we'll use add expense and then we can remove this else condition and inside this first if condition we can set underscore title equals edit expense and then we can move this app state DOT set inner page title to after this if condition and here we will use this underscore title like this and we'll use this underscore title when passing this heading to form content okay so whenever we pass some string data to some string component property then we should add this as underscore so that it can get to know that this is some variable if we remove this now it will consider this underscore title as a string so it will render underscore title but which which is not correct this underscore title is a variable which we are using so for string properties we should add at the rate fine so save let's try it out I'm re-running it let's try some some food and edit expense edit expense save everything is fine and it populated the data so here let's fix this typo so we'll say some food and we'll modify the amount instead of 12.34 we'll say 3 4.12 okay save expense and now this total has changed and this some food this also the price and the amount and this text these both of these has changed right try first one yes it got up uh in the edit mode now let's try add expense so now we are in create expense mode and here we can see everything which is fine cool so add expense added expense both of these are working now we'll work on edit trip page so we are going to edit a trip and for that what we will do so where should that link be from where we can edit it so that link we are going to have on this single trip page this tab bar icon so this edit icon should be here and if we are on this page edit expense or add expense we don't need any icon here this tab bar icon we don't need this and if so on this page this is fine but when we will go to trips page we should have a plus icon here by tapping on that we'll should open a page for creating a new trip adding a neutral basically so the point here is we need this tab bar icon to be dynamic and that too optional so we can have any icon we want we can have any action on tapping out of that icon and on certain pages we might not need any icon so all this thing should be dynamic and optional okay so let's try to think what we can do this is going to be a app level thing because it will be it can be applied to all the pages in the application so it belongs to this App State now let's go to App State in App State we need this thing and if we think about it we need to have at least two things one is icon and the second one is the action which will be performed when we tap or click on that particular icon okay so what we'll do in our models folder we'll create a new model add class empty class and we'll call it tab bar item okay let's make it as a record public record or public read-only record strut tab bar item and here we'll have two things first string icon and the second we'll have a action delegate so we'll say on tap and let's have it in a label should we have it in a label uh no so we'll say on tap like this okay we have this tab bar item now now let's go to App State here what we'll do we will have one more property here so we'll say public and here we'll have array of tab bar items and the name will say tab bar items like this okay now we need to have a mechanics here we can say array dot empty table item like this the default value now we can have some methods so we'll say public void we can say add never right or sorry add tab bar item and temper items let's say multiple items although we are supporting only one item right now let's make it dynamic menu it means we can accept any number of parameters so we'll use parents with the tab bar item and we'll say Tabor items like this and from here what we'll do we will directly modify this tab bar items equals this type of items okay because this is an array so it should work directly now the hmm now we should notify the changes same way so we have two approaches either we can use this full property for this tab bar items as well so we'll have one private property with the default value of this then forget we'll return that and for set after setting it will notify same thing or we can follow this approach we can manually call this notify from here and here we'll set tab bar items that this thing has changed cool add tablet items then we'll have one more method here so if on some pages we do not want any tab or item so we can have a helper method where we'll say no Tap bar items okay and we will not get any item here from here let's call the same method previous method here we'll set add tab bar items and from here we'll say array dot empty tab bar item like this so we are passing empty array to this one so this will be an empty array which will be assigned to this so now it will be in the previous state cool now we are going to use this tab bar items so right now we have two layouts so we are going to display these items on those layouts because those has the header part so first we have main layout on Main layout this user Circle icon now we are not going to have it hard coded here instead of this what we'll do we'll add a if condition here and in this we'll say App State DOT tab bar items dot any or we could use length if this is greater than 0 that means we have some tab bar items which we need to add on our page okay so inside this what we'll do we'll have a mean label should we have a label okay let's have it and here we'll apply for each inside this four is we will say temper item in App State DOT tab bar items okay the alignment is very bad here I don't know how to fix this on vs4 Mac so I need to manually move this when I hate this thing about this vs format okay now we'll display the icons one by one so I class we will have BX as default and then we'll have text dark as default okay so the color of the icon it is going to be black and BX we are using box icons if you are using multiple icon providers so you need to use multiple different icons and you if you want to have full control over the color of the icon you could remove all these from here and you can provide all these in tab or atom directly but I'm not using that so I can have this directly here and after this I'll say tab by item dot icon so this is the icon class main icon class from box icons okay after this we are going to provide on click and on this we'll say tab bar item dot on tap like this cool what is this underscore is this something what is this underscore I don't know what is it is it actually something or just some indication I don't know okay so we are setting it here we can copy this thing and move to the inner Pages layout here also we will do the same thing we'll remove this hard-coded icon and then we'll use this step where I can this Dynamic logic here cool now if we run it we will not see any icon anything because we have not set this tab bar items now we need to set these tab bar items so these will be page specific so we will add these items on page level so first let's start all the pages one by one so first we'll go to home page and home page we need user icon so for this we can simply get this BX user Circle bxsm these two things so we are on home page and on home page in on initialized async when we set up set appstate.set selected menu items after this we'll say Upstate Dot add tab bar items now we can add our tab bar items using new first we need to provide icon which is going to be this BX user Circle bxsm and the action that is going to be it should be go to settings page so here we can say navigation manager Dot navigate to and it will be settings like this like this what is the issue now this is coming from this this one is from this this one is from this yeah everything should work now what is the issue here add tab bar items new tab item okay it was not able to figure out oh my God what is it okay fine so this is fine we just need to set this one icon on the home page now let's move to the second page which is going to be in our case save expenses page so save expense page we don't need any icon any a tab bar item at all on this page okay so what we can do we can say Upstate Dot no tab bar items like this cool save trip page on safe trip page we need one icon which is going to be the edit trip icon here we will say Upstate dot add app state dot add tab bar items and here we'll say new table item and the icon we are going to use BX I think edit or pencil something like this I don't remember bxsm and on tapping of this we will redirect user to edit trip page we are on save tripation save trip on Save trip we are not going to have anything so here we'll say Upstate dot no tab bar items this was save trip after that we have settings page on settings page we'll see later sign in sign up single trip page on single trip page we are going to have edit icon so here on initialized async we will have this and from here we'll move to edit uh edit trip page so for that let me copy this that is going to be an inner page so here we'll say go to edit trip page like this and here we can have in trip ID or we can get it directly from the property because this page is related to single trip only okay so it will be go to Inner page trip strip ID and then we can say edit this page does not exist will work on it now so on this save trip page right now it has only one thing for trips add we will add one more for edit but right now we are just setting this uh these menu items tab bar items so let's finish this first then we'll work on that so we'll say go to edit trip page like this fine after this single trip page we have trips page on this page we are going to have App State DOT add tab bar items new tab bar item and here we'll say BX Plus bxsm and after this we will move to the uh save trip page basically so we could have a separate method or we can directly call navigation manager here for that we need to inject navigation manager so we'll inject navigation manager navigation manager and this navigation manager will call it here navigation manager Dot go to Inner page because this is going to be interface now and the URL will have trips slash add like this save okay now save everything there is one missing piece now if we go to App State where is our App State it is here from here we are notifying the select we are notifying tab bar items we are using this tab bar items on our layouts so main layout and uh inner page layout but we are not using this so if there is some change in tab or item we are not re-rendering the component because here if you check we have this condition if the selected menu item has changed then only we'll use state has changed but that is not correct right so what we need to do we need to modify this condition after this we'll say if this is selective menu item or E dot property name equals equals name of App State dot tab bar items wait a second now it should run re-render for both of these cases if selected menu item changed or tab bar item changed right so we'll add this same condition on that inner page sorry inner Pages layout on here we have this inner page title after this we'll have this condition if we dot property name equals equals App State DOT tab bar item that means if tab bar item has changed then also will re-render this page let's run it let's see if we see the correct icons tab bar icons I'm missing something and what is that something trip space this is navigation this is table item and there should be additional one run okay app is loading on home page we can see this icon if you go to trips page we can see this plus icon if you go to create a trip page we are not seeing anything go back we are on settings the same plus because on settings we did not change anything go back to home this one trip details we can see the edit trip expense nothing so that means step bar items is working displaying correctly now let's see if the functionality is working so on this home page this user icons we were navigating to settings please let's try it out and yes it went to settings now on trip space this plus it should lead us to the create new trip page correct it went there home if we are on detail page single tree page then this edit icon should lead us to the edit trip page that page we have not defined yet that means this functionality is also working so the functionality is working now let's try to continue working on save or let's say edit trip thing right so on single trip page we had this URL let's add this URL on Save trip page we'll add one more page here and then we'll use the strips trip ID and this is going to be int and then edit so we need to have one property here to capture the trip ID so we'll say public label int trip ID winner label because for adding case for this first page directive there is no trip ID so it will be null so we need to make it nullable then we'll add parameter to this cool save now when we are inside this own initialized async after fetching all these things we will check if this trip ID had some value and that value is greater than 0 we could use shorthand greater than 0 so it checks for null value if this is null this condition is going to false if this is actually 0 then only actually greater than 0 then only this condition will be true in this case what we'll do we'll say model equals a weight trip service dot get trip async tripid.value and then second parameter we will make it false include expenses false because on this page we are just modifying the trip details we are not doing anything related to expense on this screen so the second parameter should be false which is by default fault so we can skip this like this cool now we have model values to edit other things will work same as these were working before there is only one thing which needs to be changed if you see this heading it is add a trip right same thing goes with this set inner page title added trip we need to make it Dynamic so we'll follow the same approach we followed on Save expenses page so we had this title so we'll use the same thing so here we will say private or let's call it heading private string underscore heading and we will have a default value add a trip okay and inside this when trip ID is greater than 0 there we'll say add it trip okay and then we'll move this line this set inner page title to after this and here we'll say underscore heading and the same underscore heading variable we are going to use here on this form content so we'll say at the rate underscore heading and now everything should work same with this added trip additional functionality let's try it out it says let's go to some big strip edit and we are on edit trip page which is selected text is selected location day trip status everything is selected let's change the status to ongoing save trip this status changed here ongoing and if you move back if you go to the home page okay here it is just showing the correct data okay let's work on the next piece which is going to be the trips page where we are displaying all the types right so this trips page cool we added this tab bar item we added the main selected menu item so the page title and now we will work on displaying all the trips first let's inject trip service call it trip service I'll rename all this after completing all this I'll rename all this okay here we'll say we need more introop as well so I'll inject Maui cool after setting this tab bar items and select your menu items we will say Maui dot show loader after this we will fetch all the trips so for this first we need to have some State variable here to store all the trips so we'll say private innumerable trip underscore trips equals default value innumerable dot empty trip now let's use this underscore trips and we'll add data to this so we'll say await trip service dot get trips async with page number going to be 1 and count is going to be 10 and in this case I am not using paging to display this but you might you can get it as your assignment you can implement the actual paging right now I'll have something like 1000 records this does not make sense in real life scenario we should have some paging so maybe you can implement it as a endless scrolling so you will have 10 items first when you will start scrolling if you reach to the very end it will load the next page data next set of data next 10 items or you could have the load more button so after reaching at the very end we will tap on this load more icon and then it will load the next page records in this case maybe 10 10 if you are using count of 10 then it will re load next 10 items and append to the list something like this okay or maybe do let me know the comment if you want me to implement this so I can create a follow-up video on this in that we will add this paging and maybe you can uh drop some comments if you want some additional features to this so maybe I can create a new follow-up video in which I will try to implement add all those features which you are going to request in the comment box okay so do let me know in the comments cool so we have trips now after this we will say Maui dot hide loader we don't need this loader now tool now let's use this underscore trips here first thing we will check if trips dot any and we'll check the negation if we do not have any trips then we'll display something and if we have some tips then we display something else so when we do not have any trip let's have a main container before this so Dave class container in this we'll have this conditions and if you do not have any trip we'll create a div class let's say empty trips container okay in this we'll use deflex display Flex Flex column so the same approach we are using on uh home page right we are just using similar kind of thing on home page this thing let's use this copy this come here and paste it cool you haven't added any trip yet and go to add a trip page let's create this method there so go to add trip page like this go to add trip page and we need navigation manager so let's inject navigation manager so we already have navigation manager here cool so we are using this here like this the only thing we are going to change this empty trim strips container we will remove this mint vh50 because on this page we need this to come fill entire page so we'll add some styling to this empty trips container so let me add style type text CSS will make it scoped only and empty trips container and here we'll say height we will use calc function and here we'll say variable what was that neighbor height the height of the neighbor right so let's go to Triple W root and CSS app.css neighborhood this thing let's go here here we'll say 100 VH 100 of the vertical height viewport height minus variable of this one so it will be in our case hundred percent of the height minus 50 pixel which never height uh takes basically empty trips container if this is the case we have this add a trip and on tapping on this we are going to go to the add trip page now we can do one thing go to active page right so instead of using this here on this tab bar icon we can directly use this go to tab bar go to trip add trip page fine save everything cool this is fine if we not have any trip now we'll use what if we have some trips data already so we'll display those so we'll say div class row p y 3 so some vertical padding after that we'll add four each we'll save our trip in underscore trips okay and then we will have all that trips and for this we'll use complete width so we'll say div class call 12 complete thing then mb3 margin bottom three inside this we'll use a card so we'll say Dave class card inside this card we will use a div class H stack horizontal stack so we can display the items in columns and we'll use Gap 3 to make to give some spacing between the horizontal stack between these two items on the page here we will use image first so IMG SRC this will be trip Dot category image and on this we are going to add a class and class let's say trip IMG like this after this IMG we are going to have a vertical line so for this bootstrap gives us div class VR vertical rule which is for vertical line same way we have HR which is the default HTML element for horizontal rule cool after this VR and H tag inside H stack only we'll create a new div with v stack so this is going to be uh vertical stack with P2 padding of two and here we will start adding first we'll add the trip name and its status so for this we'll say div class deflex justify content between so we will have status and this at Each corner and then vertically centered so align items Center inside this first H3 H3 here we'll say trip.title and then second section where we'll suspend class rounded pill BG let's say primary text White margin 0 p x 2 and font size 12. inside this we will display the trip dot display status okay after this div now after this uh this div where we are displaying this title and status we'll display on label with class m0 p x 2 and P Y 1 here we'll display the location so we'll say I class BX BX map for location padding 0 and me to margin and 2 so that we can display the actual location and here we'll display span trip dot location like this then we'll copy this label paste it again and this time we'll change this map to calendar so we are displaying uh dates here and then span will say trip dot prom date in our case so we'll say two short date string hyphen will say trip dot to date dot two short date string like this cool so this looks fine and when we tap on this card it should navigate us to the single trip page trip Details page so let's go to the home page we'll copy that method from there so on home page we should be having go to it go to single trip page this one let me copy this method come here add this method here go to single trip page we'll use it here on this card we'll say on click equals we'll call this go to single trip page and we'll pass trip dot ID to this one cool let's try it out so I'm going to run it is running on iPhone okay okay app is here let's try it out uh trips page we can see the trips image is huge so we have this trip IMG class let's add some styling to this so here we'll say dot trip IMG and we are going to set let's set height or width we can set one thing or let's set width to be 100 feet save rerun okay go to trips and it looks great it looks great rounded pill this class note applied Let's see we might have missed something we are on trips page status rounded pill spelling stick rounded pale okay right now we are having this BG primary fix color we could use the same approach we used on a trip single trip page right to display the status this thing or if we are doing this at multiple places let's do one thing let's copy this logic go to the trip class and here we'll create a new ignorable properties so here we'll say we'll create a computed property here we'll say status color BG or status BG color background color basically cool here we'll add the same logic we just change this underscore trip to direct trip like this and this says like this so status busy color we are applying switch statement on this status here let's remove this get set we don't need this now okay and we'll add ignore to this one as well ignore cool now we can use this direct property status BG color on our single trip page so here instead of doing all this we can remove this thing altogether and we can use this directly underscore trip Dot status BG color like this and similar thing we are going to do on trips page we have single trip on this after rounded pill we'll say at the rate trip dot status BG color save everything let's rerun okay app is here let's go to detail page ongoing which is in green which is fine alone trip this is planned in BG secondary let's go to trips page let's check it out here ongoing plan plan completed so the colors are changing right cool everything looks fine now let's go to some detail road trip we can see this ad expense go back go back everything looks fine now everything working as expected cool now let's work on this settings page I guess this is the only page which is remaining now everything else is done all functionalities are working as we expected these to work cool let's work on settings first let me stop this and let's close all the pages close all tabs we'll just open our settings page settings page fine here we are setting set selected menu item and after this let's set App State DOT no tab bar items okay cool okay here first we'll have a div class container with some padding P3 okay after this we are going to have something and that something is going to be div class will have display Flex column justify content Center align item Center and then we have we will have some class here let's say uh we will need complete height minus the main tab bar okay let's do let's call it h remaining the remaining height remaining we'll add some styling to this H remaining and this is going to be Style type text CSS code and here we'll say h remaining so we'll say height which will be or let us say mean height no let's use height only because we know what item we are going to display we have limited set of items so here we will say calc Kelsey 100 vertical height minus variable and here we'll use never bar height and we'll use 100 pixel additional uh Gap I'll show you in a bit how we are why we need this okay after this what we'll do we will display one uh that user initials in this app we have not implemented users profile picture so we'll mimic that using the usernames initial so for this the first item inside this div Flex will have one label with couple of classes first we will use rounded Circle which is the complete circular shape then we'll use text uppercase to make that in uppercase we'll use BGE success BG gradient text White text Center FW bold this is phone to weight and after that shadow LG so large shadow and then let's have some custom styling as well so I will add one additional class Avatar which is our own class we will add something to this sorry now we need user initials and that initials we need to somehow get from somewhere and from where we can get it user related things are in one of our service which is auth service we have it signed in we have set user set user sign out here we are going to have one more property so we'll say public logged in user we'll say current user okay this is going to be a computed property and we know we are storing user details in Json format right where is a set user method set user this one we are calling logged in user.2 Json so we are setting the data this current logged in user using this logged in key right so we can directly get the data from this preferences when this underscore preferences dot get type of data we are storing at string and the key is going to be logged in user now what is the name logged in key this one now this is in string format we need to cast it to logged in user so what we can do we can go to this logged in user method this struct where we have this public string 2 user method here we'll add one more method but this time this is going to be a static Factory method so public static logged in user and this will say load from Json and here we are going to get a Json let's have it in a label to handle unexpected cases and here what we can do we can say first we will check if this string Dot what is the issue okay this string Dot is null or white space Json if this is the case we'll simply return plugged in usual logged in user default we should return default if that's not the case we know we have some data in Json this string so we'll deserialize this so we'll say Json serializer Dot deserialize type of data would be logged in user and data will provide this Json okay so now we can use this thing directly save everything load from Json here we will say uh logged in user dot load from Json like this what it is saying this is saying that there is no argument given to the question required parameter default value okay when we called get we need to provide default value in this case default value will provide string dot empty cool so we have current user now okay but if this is null or empty we will return default when we say default logged in user will have default values so default values means ID 0 and name null these are default values for integer and string so we need to consider these also when we are adding some data to the pages so here we'll get the initial and when we say initial first let's inject our auth service both service let's call it auth only here we'll say Earth dot current user this is now never going to be null because this is struct so it will always have a value either the default value or the actual value after that we will have name and on name we are applying this 0 we need the first character now here is the catch if the name is null then it will throw exception so what we need to do we will need to add this question mark So if that we have value then it will display that if we do not have value it will simply skip this cool so we have added this after this we are going to add couple of items menu items or maybe settings we are system provides so here first thing we will save Flex grow one we need this div to take as much height as the remaining in this display Flags after this one we will have the last part we'll use this fold as sign out button so on this we'll say BG Danger rounded pill p y 1 PX3 text White m0 display Flex align items Center and in this we'll have one icon first so I class BX it will be b x log out this is the icon here we'll have M 0 p 0 and m e 2 to make some spacing to the right where we have our span and there will display sign out this text cool on clicking on this we need user to log out so here we'll say at the rate on click on click we will call a method we'll say sign out let's create this method so here we'll say private void sign out we have our own service we'll say auth service okay we have injected it as both DOT sign out like this okay so after signing out we should redirect user back to the sign in page so here after signing out we'll say navigation manager and we have not injected this let's inject this navigation manager at the rate inject navigation manager we'll call it navigation manager only so navigation manager dot navigate to and we'll say sign in and here we'll set replace to true because we do not want user to come back to this page cool we have signed out redirected user back to the sign in page and now we are good cool okay let's try it out how to how it looks right now then we'll work on the setting items okay it's here let's go to settings and we can see something so we have the sign out button then we have this a we will add some CSS styling to this to this Avatar this uh CSS selected okay so let's add some things first let's have some fixed height and width so height 80px with atpx and font size let's say 50px no very big font size fine let's rerun let's see settings and this looks nice okay now let's add the settings or system supports let me stop this and in this div class Flex screw one we'll add couple of other classes so first we'll have some margin on the y-axis so m y 3 py2 padding then we'll have width hundred percent then we'll have display Flex inside this and then align items Center like this inside this we will work v11 UL with some classes this list group these classes are coming from bootstrap so we have this list group in bootstrap I am going to use those classes so list group then list group Plus and W 100 inside this we are going to have couple of Ally items and these Ally items are going to have list group item class inside this we will have Dave class H stack Gap three first we'll have python so I class BX bxsm a bigger icon and first we'll have BX user and here after this we will have a span where we'll say my profile profile let's use label like this okay now let me copy this a couple times two three four after my profile we will use change password and the icon will be BX lock and here we'll say change password change password after this we will use one setting to manage expense categories and the icon we are going to use is BX grid okay this is all what we are going to need and this last item let's add some thing here so inside this we'll say label class no class here I'll add my name so I'll say made with class icon so BX bxs heart B uh we'll say text danger to make it red okay made with love by Prince and on this I am going to give link of my YouTube channel so here we'll say let's have underline and bold so you strong and after this I am going to have a tag here from here we'll say https www.youtube.com slash at the rate up by Prince but to add at the rate in a Razer page or CS HTML page we need to add double at the rate so here we'll say a by Prince in the text I am going to use a weapons like this cool okay so everything looks fine now hmm fine okay now when we say my profile or manage my profile in our profile we have name username and password right so password I mean using it here so change password we can change the password and for username there is no point of changing it then we have name so this my profile in our case in this particular small application my profile means we'll give user an option to change his or her name but in a real world scenario real world app if you have couple of things in the profile you will have Avatar you will have name email mobile address so many things you can have so you can create a new page and on that you can have that form from where user can change its profile details in my case I am going to have only single value name change and from change password I am going to give user ability to change its password so this will also going to be a single uh value change so for both of these instead of creating new uh instead of creating new pages I am going to use something called prompt so this is a device a specific pop-up which comes with one text box and we can add our text to this and we can save that so that thing we will use for both of these my profile and change password then for manage expense categories for this I am going to have a dedicated page because on that page I am going to list down all the previous expense categories and there we'll have one option to create a new expense category okay so for this prompt thing this is device specific so this will go in my interrupt okay here we'll create a method where we'll say public async task string and we'll say let's say to prompt async here we'll have string title spring message and string let's say OK button text or can we have it I think yes let's check it out okay here we have app dot current dot main page dot display prompt async this one in this we can have title message accept cancel placeholder okay we are going to use all these so title we'll use title message we'll use Messi accept is going to be the OK button text yes then placeholder Place holder okay it returns task of string which could be nullable if you press cancel so let's accept this as well so here we'll say string placeholder like this we will return await this complete thing cool now we can use this show from tracing on our page settings page here we are going to create couple of methods first private async task here we'll say change name isync ideally we should have this the actual logic in odd service because this is related to user profile user password right cool so here we will have these methods public async task and then first we'll say change name async string new name and similar way we will have one more method for changing password okay so for this we'll use word DB user equals of weight context Dot get or let's say find async type user and we will use the current user's user ID so we'll use current user dot ID so now we have database user we will set DB user dot name equals this new name and then we will update this user back to the database so we'll say await context dot update item async and we'll add this DB user like this after this we will modify the user by setting the set user because now name has changed we should use this set user with this new value set user DB user cool let's copy this same method paste it one more time for password so here we'll say change password async string new password and instead of DB user.name we'll say DB user dot password equals new password and this time we don't need to set DB user to V we don't need to set TV user right because password we are not purchasing password in the in preferred this preferences right share preferences so we can skip this thing from here Cool Change name is change password async we have these two methods in auth service now let's go to settings page and here we have change name async first thing we are going to display our prompt here so here we'll say where new name equals await Maui dot show notes Maui dot show let's inject Mao interrupt inject Maui introop Maui and here we'll say Maui Dot show prompt async okay here first title so we'll say your name then message here we'll say enter your name then Third One Ok button text so here we can say save and then fourth one placeholder so in this placeholder we can display the current user name so we'll say Earth dot current user dot name like this cool now it will return an enable string if user added some thing in that box and press save then it will return the new name and if user canceled pressed cancel button on the prompt then it will this new name will be null so here first thing we will check if not string dot is null or white space new name if this is not null or white space then only we are going to update this in the database so here we will say await auth dot change name missing this new name like this save move it like this cool change name is sync it is done let's copy the same thing paste it and this time we will do this for change password async and show prompt async in this prompt we'll say the title is going to be change password mass is going to be enter new password the button text is going to be save new password and the placeholder in this case we do not want any placeholder so we can say string dot empty tool now if we actually provided some password let's rename this new name to new password and now we'll use this new password Here new password if that's the case we'll call a method change password async with this new password like this cool let's use these two methods here so first we have my profile on this Li I am going to add on click and here we'll say change name is sync on the second one change password here we'll say on click change password async like this fourth one we already did this then manage expense categories let's add here also here we'll say on click and here we'll say go to manage expense categories page let's create this page this method here so here we'll say private void this method and from here we'll say navigation manager navigation manager navigation manager navigation manager dot go to Inner page this is going to be a inner page okay here we can say let's say manage categories directly manage expense categories expense categories tool now let's first check these two things change name and change password then we'll work on this manage expense categories let's run it app is here let's go to settings and we can see these change my profile change password manage expense categories for my profile your name enter your name okay this is the predefined value no I made some if we press this up here nothing change password save new password what about the cancel button um interrupt placeholders oh after title message we have OK button and after OK button we have cancel button so this placeholder this should be like this placeholder okay stop and rerun this uh the positional argument this placeholder it was for cancel button so that's why it was showing differently now we added this colon here so we are setting this optional argument optional parameter manually okay we are here app is loading settings my profile and now we can say cancel save and if you see the placeholder for this is above which is the current user's name cancel then you change password we have change password enter new password save new password and cancel button I think this happens now my profile instead of away let me add prints save and you see this changed and we can see this P here because now the name has changed to Prince if we check my profile we can see prints here same thing will go with password with if we press this nothing will happen if we press something else we should show the loader as well right so on settings page when we are doing this thing we should show Maui dot show loader and then Molly dot height loader same thing with change password we'll say Maui dot show loader and then Maui dot hide loader cool okay so this thing is working fine now let's work on the this manage expense categories right now there is nothing on this page which is expected we have not created this page now we'll create this page so for this let's go to our Pages folder add new file asp.net core Razer component and here we'll say manage expense categories [Music] page okay and for this we could take inspiration from some inner page because this is going to be an inner page so on this let's say save expenses page let me copy Avenue it will be a lot okay let's do a couple of small things so first layout should be inner Pages layout before that we'll add page here we'll say manage expense categories this is the page URL layout is inner page layout and will inject our App State we'll call it app state only and inside this we will override on initialized async method so we'll say private async override task we'll remove this here we'll say App State DOT set inner page title here we'll say manage expands categories after that we will say Upstate Dot add tab bar items here we will head one table item to create a new expense category so temper item it will be BX bxsm BX Plus and the operation action is going to be let me create a method here private async task will say add new category something like this add new category async copy this and here we will simply call this method this is available we can skip this because there is no point nothing we are waiting for so we could we are good with this one okay save it everything looks fine now now before working on this add new category first we need to display the categories here so for this what we'll do we'll do we'll have a state here private string array here we'll say categories with array dot empty string and we will inject a drop down service inject drop down service because we already have a method in this drop downs service or that getting the expense categories drop Downs okay after setting all these here we'll say underscore categories equals a weight drop downs dot get expense categories async and we'll do Maui so let's inject Mao interrupt as well here inject Maui interrupt we'll call it Maui only so Maui dot show loader then we are fetching the categories from the database after that we'll say Maui dot hide loader cool now we have categories here we just need to display these categories here so on here we'll have a div slash container we'll have some padding so let's say P3 after this we will have Dave class row in this we will have Dave class call 12 so complete width and here we'll use UL class list group with some margin and Y3 and padding top 5 so that we can have some additional padding on UL after this we'll have for each Loop where category in underscore categories like this and here we will simply display this category in Ally so we'll say Li plus list group item and here we can display this category cool what is the array on initialized async non-initialization okay let it be now we have this add new category which we are calling from here so now here first we will display the prompt so we'll say where new category name well let's say new category only we'll say await Maui dot prompt testing show from testing title we'll say expense category message will say enter new expense category name name after this OK button so we'll say save then placeholder for that we'll say enter category name cool here we'll check if not string dot is null or white space new category that means user has provided some category name now we need to add this category to the database so for this we need to uh add that logic so let's go to drop down service we could head with in maybe some separate service we could have this in trip service or maybe in our case let's add this in drop down service although the name indicates it is related to drop down so it should be used for patching only okay let's do one thing let's add these two trip service here we'll say public async task of method result here we'll say save expense X pens category is sync string category name like this okay here first thing we will fetch the DB category for this category name so what we can do we can say a weight context Dot uh get or let's say find async expense category and here we can pass the primary key in our expense category case this particular case name is the primary key so we can use this directly here so here we'll say category name now we'll check if we have this category or no so we'll check we will get this DB category if DB category is not null that means we have this category name in the database already in this case what we'll do we'll return method result method result dot fail and the error message is going to be that category will display the category name category name exists already so this category already exists like this if that's not the case we will simply add this await context dot add item async expense category and then provide the value so we'll say new expense category with this new not new category name like this and then we can return method result dot success like this cool let's use this save expense category async go back to our manage expense categories page here let's inject trip Service as well trip service trip service and here we'll say if this was the case first we'll show the loader show loader then we'll save our result equals a fate trip service Dot save expense category is sync with this new category after this first thing we'll hide the loader after this we will check if this result towards its success if this was successful then we'll do something or let's do the negation if result its success is false that means saving was not done so in this case what we'll do we will display error alert to Maui dot show error alert async here we are displaying message so message will be result dot error if we did not get it we can simply display some generic error message so we'll say error in Saving expense category category like this like this okay if this was not the case so we'll add one else condition and in else if the result was successful we need to somehow reload these categories so that this new value comes up here shows up here so for that what we'll do we'll simply extract out these three things show loader loading categories hide loader we'll create a method here so private async task we'll say load categories async and we'll do this logic here and we'll call it from uninitialized async so we'll say await load category racing and the similar call same call away load category async will do in here so when the creation of new expense category was done then we can reload the categories cool so it looks fine now cool let's try it out run we have some category which is on initialized async or it should be protected protected cool run okay app is here let's go to settings manage expense categories we are here manage expense categories and now we have this problem for this what we can do we can say manage categories save just run it other approach could be we can use text truncate but that does not make sense because we will not be able to see the complete line so there is no point of having that so let's use the smaller uh small text okay app is coming what's this why is it taking much time okay it's here go to settings manage expense categories and we have these categories now food fuel entertainment shopping others let's create a new category okay if we cancel nothing will happen if we press this there's no point of having this additional margin writing right let's remove this My3 pt5 let's remove this save rerun app is coming okay loading go to settings manage expense categories fine we have all these categories after this we have Plus new category here we can have some other category let's say I don't know internet save it did not come right we saw that loader but after that nothing happened let's see if the that error alert this thing is working actually let's try to create the same category which we already have food category food exists already that means this one okay now we have Internet that means when we say a weight load category async it did not trigger the re-rendering let's try it out one more time and some new category save and loader was there but nothing happened okay this time it is not able to figure out that something has changed so we will manually tell it maybe after saying this await load categories async will say state has changed so sometimes Blazer is not able to figure out if something has changed or not in that case we can manually trigger the state has changed let's try it out rerun okay settings manage expense category some new category let's create a new category again again new category save and this time we can see it so looks like this is working fine we have added these three categories internet some new category again new category let's go back go to home or maybe trips let's go to any trip go to add expense here this category we should see the new category so we can see internet some new category and again new category so we can see these categories here so things are working fine cool so I think everything is working now on the settings page let's do one thing let's have one icon here the tab bar item so for this we will go to settings page and here when we have this tab bar I terms I said no tab bar items instead of this let's do add Tabor items we'll add one table item with icon we are going to use bxsm and here we'll say BX info Circle after that the operation on Tab I am going to use I will use something that is launcher dot default so this comes from Maui launcher dot default we can directly use it here or we can move this to my intro because all the Maui related stuff device related stuff we have added in Mao interrupt only so here we'll say try open async and here we will provide URI in our case the URI is going to be the same as this URL complete YouTube url this time we will add single at the rate because this is not inside the razor like this this and then this fine save everything it should work but to make things clear all the Mario related stuff we have in our mouth interrupt so we can cut it from here we'll go to Maui interrupts and we'll add a method here here we'll say public async task show in launcher something like this or open in launcher okay we'll say string URI like this and do this await this thing and now we can use this directly in your settings and here so here we'll say Maui Dot open in launcher and we are going to cut this URL we'll use this Ura parameter here and we'll pass that value from here cool so we have these this is from Opel launcher this is from here we'll have one more like this cool let's try it out let's restart the app this time we should see one eye box on the settings page and when we tap on that it should open the YouTube app or YouTube in the browser in mobile browser okay go to settings we can see this I button if you tap on this it is opening browser in this case youtube.com and it should open my channel cool go back looks fine from this by Prince also it should open the same thing my profile we have this change password we have this manage expense categories we can go to expense category we can create new category so everything is working fine as we expected let's try the sign out button sign out and we signed out it uh navigated us to the sign in page from here we can create account sign in same thing let's try I don't remember what was the password in correct credential incorrect credential what was the password okay do you guys remember what was the password do let me know in the comment if you guys remember we created this uh at the beginning when we implemented those screens cool so everything looks like everything is working fine as we envisioned and we as we saw in that sample demo app cool let's try it out on Android how it looks on Android the complete app pixel open Android emulator it is coming Lotus recent trip trips we have this trip we can create a new trip some Island some Island here trip location and Iceland on the west something like this trip start date trip and date and trip status let's say this was canceled maybe save trip we have the safe trip with some Island canceled we can see this ad expenses we can add expense something like tickets how much 12.35 choose category it was let's say others when the same day save expense we are here we can see this so things are working let's try the settings okay my profile let's change the name to Prince save it got changed change the password one two three four five save new password manage expense categories we have these categories Plus here we'll say let's say we will change we will add a new category tickets save go back and now let's go to trips or maybe home here also we have some Island this tickets let's change the category here so this is added expense here we can see this tickets category select it save expense and now we can see the stickers category here so everything is working as we envisioned it should work let's try it out this I button so I we tap on it what happened this isn't working did we try tapping on anything yes it works what is the issue here did this works well this thing is working update your app no I don't want to update I button is not working let's see what is the issue here oh maybe it is the same issue sometimes okay let's try first let's try sign out sign out is working maybe one two three four five sign in we change the password to this go to settings and this icon this is not working one tab is not working on this one on settings uh tab bar icon my interrupt launcher let's add a breakpoint here if we tap on this it is not come yet came to this continue and then nothing happens continue continue oh I clicked on it multiple times file not found what is it okay let's try one thing I'm stopping it I am going to uninstall the app on okay something is not right with Android emulator something is not right with Android emulate let me close this and open the emulator again so I'm going to close this Android emulator I am going to uninstall the app then I'll try it again let's see if it works okay so I uh closed standard emulator I uninstalled the app then I started again and again I am having this same air nothing is happening and then I looked it closely I am using try open async method it should be open async let's rerun app is coming let's go to settings I am having this slowness in the Mac and Android emulator specially now if we tap on this it went to the this should be YouTube app right this is YouTube app so it is going to open in YouTube same thing from here so this thing is working fine manage expense categories everything is working fine cool let's try it on iPhone also one more time top it change to iPhone 11 run let me pull up the iPhone simulator okay here settings top okay it went to there and here also it is working cool so everything is working fine we have successfully completed our app it took so much time but I'm sure you must have learned a lot in this long video so please do let me know in the comment what all things you uh did not know which you learned in this particular video and do let me know in the comment if you like this video and if you want me to continue making this kind of videos and press that like button if you like this share this with your colleagues friends And subscribe my channel I'll be posting uh some cool projects in future also okay so I guess that's all for this video I'll be back soon with some new cool content till then bye bye
Info
Channel: Abhay Prince
Views: 7,590
Rating: undefined out of 5
Keywords:
Id: SwCPm-IJuXE
Channel Id: undefined
Length: 530min 8sec (31808 seconds)
Published: Sat Sep 02 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.