Transcript for:
Building a Learning Management System with SvelteKit and PocketBase

hello everyone welcome to another tutorial today I'm going to be showing you how to build a learning management system with spell kit and pocket base so on my screen right now is the login page of the application so I'm just going to log in using this credentials and I'll click on the login button and I should be redirected to my courses page so in here is a table of all my previous courses that I have created as you can see we have two published and three drafts and what I can do right here is just click on this new C button so I'll click on this new course button and I'm told to create a new course by writing the title so I have to name my course I'll call this test course and I will click on continue so as I click and continue I was redirected to the course setup page and the first thing you see here is this notification of banner that says this course is unpublished it will not be visible to students and here I have the course setup title and I have to complete all FS I have one out of six so I have six FS to complete before I can publish this course the first fi here is a course title which I already given it a title previously but I can edit it so I can say C title edited so I can just say edited like this and I can save once I save you see that it shows the correct thing here but I also get this tools notification right here saying successfully updated course title and I can do the same for the description I can say C description here and I'll save this and very similar things happen and I can add an image from my course so I can click on the add image and I can either choose a file or drag and draw so I'll be showing both functionalities and how they work so to choose a file all I have to do is just click on it and I have to choose an image that's less than 4 MB so I'll click on this and I upload this one file and as you can see I can preview it here and I can also just drag and drop it from my file system so I can come here directly and I can just drag this file here into that section and I can upload that one file as you can see a file or image is being previewed and below that is the cost category where I can edit the category I can just click on photography and save that and the C chapter I'll get back to this this one is actually very important um part of the tutorial so we'll get back to this let's go to the cost price so I can give it a price I can say 30 NAA let's say 3,000 NAA as you can see I'm in Nigeria so man is In N I'll show you how to make that and the currency of your country or whatever country you want and I can also add resources and attachments so I can add a new file so the resources and attachments work very similar to the C image work in there that they store files but the attachment you can store either text image video audio PDFs whatever and I can also drag and drop the way I can drag and drop the course image so I will click here and then I'll add this docks file and then I'll upload the file so just as I've uploaded the file with this X button I can delete this file from my cost attachment so that by just clicking this I have that nice animation and that cost attachment has been successfully deleted so now going to this course chapter in order for me to publish course I need to have all six FS completed so the six FS are the ti description image price attachment and a cost chapter but by just creating a cost chapter it's not going to work so if I say my I just call this first chapter and I click on create you will notice that this publish button is still disabled I cannot publish this course still even after I created this course chapter and the reason for that is that this C chapter is um is draft it's not published yet so it's not by creating a c chapter but by publishing at least one course chapter so one C chapter has be published because if you have a course and then all your course courses your course chapters are draft you students can view them then that coures at that point is basically empty so you need to have one chapter published so in order to publish that chapter I'm going to click on this icon then I'll get to the C chapters edit page and then I can f the required fs and I would publish that chapter then I'll will come back here and publish the course but right before I do that let me just show you one functionality as you can see below here we have this drag and drop to reorder the chapters so let me create more chapters and I'll create after that first chapter I'll create this third chapter and after third chapter I'll create second chapter so as you can see they are in the wrong format I have this first chapter third chapter and second chapter so the idea thing to do is to move this second chapter to the play part that the third chapter is and the thir chapter should come down to where the second chapter is I can easily do that by just drag and dropping it there and I have reordered it it's the order has been saved in my database as well and just as simple as that I can reorder my course chapters and this is how it would show for the students so that is basically how it works and it's very nice feature so as you can see I can just drag and drop it whereever I want it to be so what I can do now is publish one chapter so I'll publish this first chapter by clicking on this icon and now when I click on this icon um on this page to um edit my chapter so as you can see I have this similar notification on the top saying this chapter is unpublished it will not be visible in the course and the publish Button as well is disabled so the first thing I the first um field I see here is the title which I've added first chapter and I can give it a description and this description here is a what you see is what you get editor meaning that I can basically have this is one yeah and I can see this is a h one tag and I can also have bullet points so I'll say first point second Point third point so on and so forth I can do underlined so I can come here and I can write and you can see it's underlined I can do stroke over I can do Bard and some other nice things with this editor so after doing that I just save this as you can see basically the way I wrote it is how it appears so what you see is what you get and now below that is the access settings where I can basically check this box if I want to make this shapter free for preview so I can make chapters free for preview I'm just going to click on this and save now this chapter is free for preview and lastly I need to add a video for the chapter obviously so I'll click on this add video button and I'll like the way we add for the image and the attachment I can drag and drop or I can just click it to choose the file so I'll click here and now I have this um video code animation I'll open this and then I'll upload F and now this video is being currently um worked on by MOX so they said video can take a few minutes to process refresh the page if video does not appear but at this point I can actually publish this chapter so by clicking on this publish chapter button this chapter has successfully published that Banner disappears and I can go back to the course and when I get back to the course you see that that first chapter that we had there now has a free badge and a published badge so it's notifying me or letting me know that this chapter is free and this chapter is published so as you can also notice now that the publish button is also abled now I can click on this publish button to publish this course when I click on publish see we have this nice confer let's us know that the course has been published at the same time I can also unpublish this course publish the course back very beautiful confed here and I can go back to our course page and as you can see in this my courses page I have all the courses that I have created and now added to that list is this test course edited that we just created and as you can see I can filter courses so I can search for just this course can see test course as you can see it's just that course that pops up here so if I had multiple courses there and I had to be and I had um pagination I can just sash we had like 30 40 courses and I wanted to just find this course I can just search for it and I will get it here so by just clicking here I can edit it and I will be able to actually edit this course and right here I have this delete or trash I I click in here I have this mod out let me know that this action cannot be undone so I can click on continue and I would actually delete this course so as you can see the course has been deleted I've been redirected to my courses page where have my coures table but that course is missing because it has now been deleted and I can redo that action by say create new course and I can create a new course again so this is basically all we're going to be learning going to be learning a lot of cool stuff concerning SP and concerning SP kit I going to learn a lot of cool stuff concerning pocket base you learn how to really get very good using pocket Bas using spelt kit using spelt and using those tools together so that's very important letar not to use them together in a very nice manner giving you the best experience is going to be something that you're going to learn in this course and before I continue I want to let you know that this project has been created previously by another Creator on YouTube and this is basically just another variant of that project using a different technology to create the same project so stay tuned this is going to be a really exciting one and as always link to the repo is going to be in the description and it's for free so all you have to do is just to give the repo a start to let me know that you visited thank you we are going to begin by installing spelled kit what I want you to do is to go to your browser and go to the Chen Spell documentation and I know you might be confused because I said installing spell kit and not installing sh but we're going to be following their guide on how to install spell kit because I think it's a very nice guide and helps you install all the necessary components you will need to run Chan later on so go to the docks and in the docks you see this installation page or link you click on it now we have guides we have a sp ke be and we have the manual we are using spel kit so you click on the spel kit and they have this use spel kit CLI to create a new project I'll copy this and I'll will copy this for pnpm I personally use pnpm and I also advise people to use pnpm well whatever one you are using you can just click on the and it will copy the command for you and go back to vs code and open up your terminal on Windows the shortcut is control J and on Mark I believe it should be command J in the terminal I'm just going to paste the command and this my app part is the name of the application so I'm just going to change the name here from my app to LMS project so I'll just call it LMX stands for learning management system and I'll click enter now we have the sprom welcome to spel Kit which felt app template you're going to be going for the skeleton project so go to the skeleton project you use your arrow keys to move up and down and then use enter to select add type checking with typescript yes using typescript syntax enter select additional options and here we will use the arrow keys again to move up and down and then the space bar to select the ones that we want and then we click enter so I'll go for ear link Prett here that's so and now click enter now we have the next step which is to CD into the LMS project pmpm install and then we can add G and all those good stuff but we won't actually do that now we would go back to the chat spell kit guide and we would also add T using spel ad so spel ad is just a nice tool that helps us add and configure ta wi CSS instead of going through all the steps all the configuration ation steps to add tail to our application we can just use SP add and it will add tail for us no stress so I'm going to copy the pnpm go back and I'll paste that there and I'll click enter so I was giving this error saying there is no valid F project in this directory and which is true so what I have to do actually is to se into that LMS project because right now I'm in this tutorial directory which is not a felt or short KET project so I need to see into the LMS directory and then I'll be able to run that command once more and as you can see now everything was successful we have P CSS successfully set up and repaired TM CSS successfully set up and now I can run this final command which is to pnpm install but since I'm using I mean npm install but since I'm using pnpm I'll be running pnpm install copy that [Music] again and I'll past that one more time and now it should install all of our necessary dependencies and DEP dependencies and we should have a node modules folder added yes so let's just give this some minutes mine was done in M seconds and not minute so I don't know how long yours might have taken this is one of the reasons why I advise you using something like pnpm or Bond because they just give you a better experience when downloading or installing all these bues so now that that has successfully installed what I'm going to do is that I don't want to be um in this tutorials directory I don't want my V code to be in the tutorial directory so I'm just going to go here and I'll say I say open folder this open folder I'll go to this tutorials folder and inside there I'll click on this LMS so I want to be opening this LMS directory directly so select the folder and now we open in this elements directory directly and now we can actually run this application so I'm just going to control J open the terminal and now I can run pnpm Dev now we have open in this Local Host 5173 I can just control click and that should open in my browser for me and as you can see we have this welcome to SP kit visit blah blah to read documentation now before we actually go any further let's explain the folder structure that we have here the first folder that you see here is called this do. kit folder you don't have to bother yourself about this folder this folder is generated every single time you start your St server for felt kit so if I delete this folder and then I cut this um running terminal and I rerun this pmpm Dev this folder will be created again so don't bother about this folder at all the second folder here is node modes folder and this folder is where all our dependencies and DEP dependencies are kept do not delete this folder because if you delete this folder that you're going to have to run pmpm I you're going to install this folder because without this folder you won't be able to run this project locally on your machine the third folder here is the SRC folder and the SRC folder is the most important folder in this whole project this is where you'll be working on 90% of the time and the static folder is where all the static assets are been kept and we have a bunch of other files that you really don't have to be bothered about about for now so let's go back to the SLC folder as I said this is the most important folder that you should be bothered about and in this sfc folder by default we have two folders and three files we have the liap folder the RS folder then we have the app. TS the app. D.S file the app. HTML file and the app do pcss file now this pcss means post CSS so if I click on this you'll see that it's basically just the way CSS work but P CSS enables I mean this extension called pcss enables you to write post CSS syntax here so if you wanted to extend your CSS Styles you can easily just write post CSS syntax here but at the same time it doesn't matter if you don't know post CSS you can just write CSS directly inside this file and it will still work the same so I advise you to leave it like this even though it's confusing you that this is not a CSS file um I'm not used to this just leave it as such nothing's going to happen you can see at your pure CSS here just for those guys that know post CSS and want to leverage the power that procss gives them they can write direct procss syntax in here and it would work because of T actually uses PSS so when we used spell add it added P CSS for us and it configured P CSS for us as well as you can see we have the P css. config the CGS file here so this is a valid PST CSS file and it would run PSS syntax if you wrote it but if you didn't write with CSS you wrote PL CSS it will still work the same now the um app. HTML is B is the root file this is very important file do not leave this file leave the file as it is for now only come here to edit it if I tell you to edit it I don't personally don't like editing anything here cuz if there's anything I want to edit I can edit directly inside my special files like if the for example the Ed or any meta tags and this SL that I can ED it directly but for now leave this file the way it is and the third one here is the app. DCS this will come back to it when we need it so just leave this as it is again this one is actually a very important file if you are using typescript so do not delete this file as well now moving to the folders that we have the the first one here is the leap folder Le folder is basically um the library folder this is where you be keeping things like components utilities files and things like that so this is actually a nice folder to have so you just leave this as well leeting this won't cost any AV in your application the way same way this app. HTML or app. CS we but leave this folder the way it is because of we will be using this folder when we are building this application and the second folder here is the route folder which is arguably or not even arguably which is the most important folder after the SRC folder and the folder is where we have our routes in it so our Pages our routes this is where we would have them and if I open that rout folder I have two files here I have the plus layout SP file and I also have the plus page do f file this is called a layout file and in this context it is the root layout and this is the page file and in this context it is the page it is the root page file so let me explain better for you you can see the things we have here we have this H1 welcome to spell and then we have this visit blah blah blah through the documentation if you notice anything this is the same thing that we have here the same content is what is here that's because this is the root page so the plus page that's spel file in the root of the routes folder is the root page and the plus layout do f file in the root of the route folder is the root layout these things are called special files in Sp kit and they enable us to do special things now in the spe in the plus layout the spell file as I called it the root layout is where you put things that you want to appear or reflect throughout your application so that is why this place is a good place to actually import our CSS file let me just format this so you can see it better now as you can see we have this script tag and in this script tag we have this import um app. pcss that file that I talked about so this is actually the ideal place to import this file so that it can actually reflect throughout our application and then we have this slot which is um us telling SP kit where to Output children and just here what I want you guys to do is to add a l equals to TS yes because we are using typescript for this application so just do Le TOS this is just a way for us to tell typescript that this script tag is going to be written in typescript and not plain JavaScript so any other thing that I want to import that I want to reflect throughout the application I will import it in this root layout and any UI that I want to put here and I want it to reflect um trout my application I'll put it here as well so if I want an Eder to show throughout my application I'll put it here if I want a footer to show throughout my application no matter what page it is and put it here as well that's why it's the root layout and this is how I create routes in Sp kits just by having this plus page and plus layout um files the most important one for creating route is the plus page just felt file so if I want to create another route let's say an about route I'll firstly have to create a folder inside the routes folder so I'll create a new folder and I'll say about and this will be the name of the route so if I go to sorry if I go to about this is the rout but right now we have this 4 for not found and the reason why it says for for not found is because of this about folder is empty we need a special file in order to actually make this a route and the special file that we need is this plus page do file so in this about I'll just have to add a new file here called plus page dot SP and then I can say this is the about file let me just increase the font for this so you guys can actually see this better I think this is better this is basically how I create routes in s kits now I can save this let me reduce this com a little bit yeah and I can check my browser one more time and you'll see that now this about is now route and as you can see we have this this is the about file or about route I think about page is be better so I'll change this to page save this and it will reflect here now this is the about page because of spelled kit as us reloading meaning that anytime we change something here we save it it would immediately or as fast as possible change it on your browser as well so let me just show that one more time let me see testing all re load and as soon as I save this bam we have t not load there that's basically how we create um routes in felt kit it's called file based routing system so you create folders and then you put a special file which is the plus page SP file inside to make it route and the name of that folder will be the name of the route and in this about file I can have a plus layout spell file to be the layout for this about file or this about page and it's children so in this about folder if I put a layout file the a plus layout do felt file it would become the layout for that about page and all the about children like about slme about SL you about SL the company would also inherit that layout as well and these are not the only two special files that we have in SP on spel kit I mean we have I believe five or six of them and the more we need to use them the more I would explain the ones that we need so we might not be able to go through every single one of them today but the ones that we need for this project I will explain to you on how they work and how to use them so that's basically how routing Works in Scot kit but before I end this section I want to show you how you actually route to a different page so in this about um page now if I want to go back to the own page how do I do it so in other Frameworks or other libraries you might need to import a link um component or some other sort of components but in SC kit you basically use the native HTML tag well it gives you the same experience as using the native HTML tag so I can basically just write an a tag there and say home page like this and above this let me put a br so I can actually break this line and just like so I have a link so this homepage is now a link now I need to actually give this a um isre so I'll say slash for homepage and now if I save that I come back to my browser and if I click on this home it would actually take me to the hom page so by clicking on this I am redirected to the hom page so I don't need to import anything I don't need to learn something new I just have the same um a tag that I would have used if I was writing native HTML so that's the nice thing about felt and sell kit is that they bring you close as close as possible to the natural ways of doing things to the normal ways of doing things so you don't have to be learning new apis and all this other stuff that you usually need to learn when you are using other Frameworks with SP and spell heat it makes you feel so natural writing this code so that is how I would navigate from page to page so if I go back to the root page and I have a a tag again and this go to the about and then I'll say about I save that and I have this about link now I can go back to the about page from the about page I can go back to the own page just like so that's all for routing for now there's any other new things that we need to learn we will learn them as time progresses so let's move on to adding fonts to our application in this section I'll be showing you how to add fonts to your spel kit application um the purpose of this session is not so that we can add fancy fonts or things like that because of the fonts that I'll be using for this application is going to be something very similar to the net font that we have right here but the purpose of showing you this is where you can go on in the future and know how to add fonts to your applications to your spell kit applications that are using T in CSS to be specific so the font source that would be using is font Source the font Source would be using is font source so the name of the website is called font source.org just like that and in here you have all sort of fonts as much as you can think of but the one we be using is called notus and the specific font we using is called Noto s so you just want notan you will notice we have different types of Nan we have no s TC not SS JP blah blah blah the one we want is Noto s preferably the varable font click on it and now we are taken to this page and we have all these different weight or weight showing us how it looks like in different weights and here we they have the install button so you go to the install button and then you see the variable the static the one we want is the variable and then we'll see installation guide for the different managers that you might be using I'm using pnpm I'll copy the code go to my terminal nvs code and I have one terminal running I don't want to actually cut this terminal so that I can download um this the font what I'm going to do is create a new terminal here by clicking on this plus button and now I have two terminals I have this one that is running the application and this one that I'm going to be using to install libraries what nice I can do is just move this terminal I can carry that second terminal and move it to the right hand side here now I can see both terminal at the same time so the one here is running the application and the one year would be for installing packages so I would paste what i c before and I will just run that so that it installs the font going back to the documentation I will see some ways I can use it so after installing it I can import it here so I can import it like this and I can also import it um import the um which the CSS and the italic I don't want to actually import both of these I just want this and now I will include the CSS in your pro in your project by adding a fing line to your project so this is how I would include it like this okay so that's all we need to know go back here as you are seen s has been installed successfully since we are not using pure CCS but we're using Tailwind it's going to be a bit different from the way they told us to do it but I would guide you nevertheless first thing I will do is to actually import it so just the way they said import it here so would copy and go to our code and the ideal place to import it just like the way I explained would be the layout the root layout the spell file because of that um because of for this font we want it to show in throughout our application we want to use Font throughout our application so we want it to reflect throughout and for that we would going to have to import it here and I prefer to import it above my CSS file it's better to import it above the CSS file so I'll get rid of this comment and I'll save this after importing it in order to make it work I'm going to have to go to my Tailwind config CJs file and I will add the font here before doing anything in this T config file I want to set up sh F because of once we do anything here and then we set up CH f it would overwrite the things that we have done here so in order to prevent that from happening let's set up CH F first and then would add the font there going back to CH documentation to that guide we see that right after all of this we have this run the COI then we have npx chassen SP athlet test in it this initialize chassen felt and it will create the component Json file and from that we can now add um components or copy components from CH and into our application when we um run the CLI would have some of this promts we have would you like to use T scripts I what I want you to do is choose yes would you like to use the style you choose a default which color would you like to use as a Bas color your Sho slate where's your Global CSS file just click on the default that was there where's your T you click on the default that was there configure the import you just click on the default and configure the import for yours you click on the default as well reason why I'm going through this one I'm not actually doing it in my terminal is because of for some days now I believe three or four days I've been having issues with using chassen felt um CLI because of possibly my location so I'm currently in Nigeria and I just moved to some different location to a place that is um relatively remote and though every other form of CLI works the chat cence felt CLI has refused to work it always shows this cannot fetch sty from registry error for me it's going to work for you don't worry there's not going to be errors it's not a Chan felt issue I believe it's a me and my location issue so you just run this here it should work the way I just explained you just need to click on yes click on enter on enter anything that says why or no you choose yes anything that shows um ask you a question just click on enter and it will work the same way it will work for me but for me I won't be a to use the CLI so for that I'm going to have to use the manual installation to manually install it manually create this component Json file manually configure my T config.js file and all those other manual things I have to do you don't have to go through that stress all you have to do is run the C and the CLI would offigure it for you and everything will be set up so I will be back once I have manually installed it and manually done everything cuz I don't want to um show you the manual steps because it's lengthy and basically it really doesn't matter to you since you'll be using the T life so give me a minute and I'll be back and I'm back if you're able to successfully run the chassen spelled CLI your Tailwind config.js file should now look like this your app.css file should look like this because of now a bunch of CSS variables should have been added and you should have a yoube file and in your um Li folder you should have this components folder and you should have this UI folder inside that components folder should look something rough roughly like this I didn't use a CLI so in my nor map your one to one but it's something very similar to this now after you've done all of this what I will need you to do is go back to your T.C config.js file and in this you scroll down to the part we have font family in this font family you're going to change this enter to what they asked us to write in font source so if you go back to font Source we have this Noto s variable copy this exactly the way it was named exactly the way was stated go back there and then just paste it replace it with replace the in with Noto s variable once you've done that I advise to cut your terminal the one that is actually running your application cut it and then rerun it so you can just use the arrow key tap up to copy the last command and to paste the last command there and you can click enter so you rerun your terminal rerun your project and I mean go back to the project refresh it and now the font should be applied you might not see that much difference in the way it looks from the older fonts because of this font is not really um a fancy font that shows um much difference from the way s works but it's the font that I want to use and make sure that you actually save this I didn't actually save this um file before I run it so save the file cost the terminal run the terminal and then you should see the change in the browser let's refresh this you'll see there'll be like a little snap snapping from the old from the default fonts to the fonts that we've added so as you can see there's a little snapping that's how you know that the font has been added and I can also show you how to stop that snapping by preloading the font so the font is preloaded before the page is actually viewed and this snapping will not be an issue but we would leave that for another tutorial and now you should have everything added the way I want it to be added go back to our plus page do sp file the root file remove everything here and just write lms2 so we are under that write felt kit Plus pocket base and now we should have that written here now that was done spell kit done the spell kit part done all the setup for the spell kit that we need for now we're going to move on to the pocket base section so the pocket Base website is pocket base. or you can just search on Google and you will get that as the first link probably now you see we have pocket base showing open source backing for your n s and mobile app in one file and very very nice um website what I want you to go where I want you to go is the documentation click on the documentation button and now we in the documentation um page the first thing we see here is a warning a clear warning straight to us straight away telling us that pocket base is still under active development and full backward compatibility is not guaranteed before reaching in version 1.0 so now pocket base is still I believe in version 0.2.1 or 20.2 something similar to that so just keep that in mind below all of that and all the unnecessary writing and writing we have the download files for your operating system I'm using Windows so as you can see pocket base is actually on 0.2.2 um whatever operating system you are using you just install the one for youra System since I'm using Windows I will install Windows so I'll click on this and the download has started I just wait for that and as that downloads I would read um all through this it says once you've extracted the archive you could start the application by running this command in the extracted directory and that's it a web server will be started and it's the following route so without have this route without have this other route for the admin dashboard UI and we have this route for the rest API once it has been installed successfully we will just go to locate it mine is located here the first thing I want to do is to extract this iive so I'll come here and say extract all directly here I'll just extract directly there and it should be extracted here now so I have this three files here I don't actually have to know what those files are doing I'll just ignore those files but in this extracted folder I'm going to run my terminal here so I'm going to use the G bash terminal I'll get bashed here if you're using any other terminal you can use doesn't matter I just prefer G bash now in this terminal I'll run that command that they asked us to run to actually start the web server so it is slash bucket base s and now as you can see by running that command I have these three um routes ready for me to use I have this one Ser at this I have the recip at this and I have the admin UI at this the one I I'm conserned with is the admin UI so I'll control click on the admin UI link and that should open the admin UI for me in my browser so as you can see pocket base has started here and it says create your first admin account in order to continue about to put in my email here my password here and confirm password here and I will create and login and by doing so I am redirected to the dashboard and I have this default collection created this users collection now you don't actually have to understand what is going on here see there's there a couple of buttons there lot things shown here if this is your first time in Pocket base you might be a little confused you have this you have this you have this you have all these things sh here but don't be worried about anything here all you really need to do is just know how to set this up I will explain all of this as we go through the um go through this course I would explain everything that you need to know about poet base but for now just know that if you on this page you are successfully set up pocket base correctly and now we can move on so after doing this next thing that we're going to want to do is go to the pocket base documentation again go to this client site sdks and in here we would choose JavaScript SDK and in here as you can see this is the pocket based JavaScript SDK what we going to want to do is to install pocket base so you see here we have the mpm installation guide I'm using pnpm though I will copy this and I'll just change the npm to pnpm open my terminal again to the part where I'm installing packages based that I don't need to use the save anymore so I'll remove the save part and I'll just turn this mpm to pnpm by putting a p in front of it and I'll click enter by installing the pnpm I mean by installing the pocket Bas SDK I can use pocket base in my application the third thing that I want you to do is to scroll down because we want to look for the spe the spell kit specific implementation so you how to initialize pocket base in your spell kit application now that we are here you see this spel kit part you just open it and here we have this one way to integrate with spel kit SSR could be to create the pocket based client in a hook handle and pass it to the other Ser side actions using event local now this makes perfect sense because of initializing pocket base in this hooks file is the most ideal way that I person can think of using pocket base in spell because of doing it here pocket base is only ever initialized once when using tools like pocket base the interface with a database out reloading can affect that and cause some issues in development since we using spell kits and out reloading is enabl um typing and saving can cause the thing to the clients the pocket base client to be reinitialized over and over again causing some sort of errors and you might not know where the errors are coming from because of the error messages being thrown are not really specific enough for you to know what's happening in order to avoid any of that initializing pocket Bas in a place where it is you are pretty sure that it's really going to be initialized once whether UT reloading is en or off is the best way to go about it so doing it in the. server.js ORS for in the handle Hook is the best way to go about it so I'm going to explain to you what the andle hook does it's basically a middleware sort of thing it's B if you understand what middlewares are then you understand what these and hooks are they would intercept routes intercept things and the nice thing about them is that they only run once on every page load so every time you have a handle hook in your project and in every folder or every route that you have a plus page. server. TS file this andle will run on that page once every on every reload so every time you reload the application the and hook would run that's why it's the IDE pleas to actually import or initialize pocket base one we can one thing we can do here is just basically copy this so we don't have to write this um manually by ourself or type this over and over again we can just copy this if you would want to type this you can just pause at this part of the video and write this down now I would go back to my application now you will notice that we don't actually have the ook dots the O file I mean we need to create the O file and the place we create the O file is in the SRC route we don't create it in this route because it's not a route we need to create it in this SRC route in the same part where we have the app. HTML the app. pcss the same part we want so what you can do is just click on this SLC folder and then make sure that you click on this s folder and then click on this new file and we write o do server. TS it must be exactly the name O which an S do server then do TS if you're in typescript or JS if you're in just JavaScript once you created that you'll paste what we just copied now after pasting it you will notice that we have one error that is showing continuously which is this PB being having this on red underline we have the PB and we have this red underline here we have it here we have it here we have it here we have some other couple of places the reason for this red underline is Tes telling us that PB does not exist on type locals so now we have locals and we have a type local somewhere but PB does not exist on it where um well spell doesn't know that PB exists and typ SC doesn't know that PB exist so what we have to do is to let it know that it's okay PB exists we can actually add PB to type loal and that is where this file this app. D.S file comes in is where we have all this um interfaces that we can actually add so that we can prevent task with errors the one we are looking for is the loc house one so we just come to this interface Lo house uncomment it and inside the col Braes we can add PB and PB will be of type um let's say pocket base and for that to actually work we need to import pocket base so import pocket base from pocket B like that save that and going back to my. CS file you will see that that error disappears and it does don't only disappear we now get Auto completion for Pb as well so now let's take a look at the code we have here and try to understand what is happening s God that we actually have comments so it'll be easier for us to understand the first thing that is happening is that we are creating this function called Ando it is important that the name is Ando that is how spuit knows that this is a andle hook and in this function we are D structuring two things we're getting the event and we're getting the res the resolve after that we use the event to um get loal and then from the loal we create PB in Lookout and then we say that PB is equals to new pocket base and this new pocket base we have this URL inside mind you this URL must be the same as the base URL here so if for any reason this is different for you make sure that you change it here as well but it should be the same pretty much so no problem there one thing that I like to do is I don't I like to the structure when I need to the structure I don't like using this do notation too much so I'll say const equals to event and I'll the structure out of events locals and by doing that I don't need to use event. loal every single time and not just event. Lookouts we have this event request as well so I would also the structure request from there as well like that now we don't need to do event the loal nor do we need to use event. request we can just say locals or we can just say events so I'm going to find every instance of this event Dot and I'll delete it so I'll copy Dot and then I'll copy event with it and I'll write control D I will sorry I would use the key Str command or combination control D and then I would find every instance of that now I'm in windows again so Mark us doesn't have control they command so it's command D and then I would delete that and the code should still work the same way save it no errors anywhere now after doing that I'll move down and I'll say I'm seeing this comment saying load the store data from the request cck string that's basically what they're doing here they're going for lookout. Pb do the store do load from cookie method and then in that they are putting the request. get cookies or if that was um undefined they just putting an mty string in there after that we have this try and cach block and this try and cach block is to get an up toate alt store by verifying and refreshing the loaded alt model if any that's basically what is happening here and after that like in the cash block they were clearing the all store on field refresh so they are basically claim the O St pretty much logging out the user after the try and cash block we have this a resolve so we are saving the aage res in this response and then we do send back the four bb or cookie to the clients with the latest store State what is happening here and then after that we return response and by returning response we are ending this andle hook basically like that so we going to actually modify and extend this handle hook to andle um authorization of pages so we don't want some certain page to be accessible to users if they are not logged in that is basically what we'll do now in this try block a commander and I'll say local do user is equals to local. PB do outto do model we have this error for lookout. user because typescript and spell kit doesn't know that users exist on local we need to make them aware by going to that app. D CS file and on PB we say local we say user sorry and user will be a type um alt model so we're going to have to import alt model first I'll just come above to where we have the pocket base Imports open my col comma then open my col brazes and I'll say type alt model and for users I will say alt model or it's possibly undefined so it's it's possibly this can be model and it's possible this can be undefined I save that file and I'll go back to my us server CS file and after doing this in this St block I'll come down to the cash block whe that was if there was an error then I'll set locals do user to be equals to Onin on error after doing that right after the try and cash block under there I would have an if block and here I want to check for the user if he is lo logged in and whether he should be able to access some certain routes or not so in this a block I would say URL now we're going to have to get URL from the um event so with the structure URL from here as well now we can actually use URL say URL dot PA name dot starts with slash now we are checking if the URL that we currently in starts slash and the user is undefined so we can just say we can say locals do user is equals to undefined or a better way of doing this is to just remove this on this part and just say not like this so by putting the exclamation mark in front of it we are just saying the local do user does not exist again let's read this again we have the if blocks we saying if urlp name. starts with Slash and the user is undef find we want to check for one thing so say and we also now we want to make sure that they are not in the login or register route because of if the user is undefined if the user is not logged in you should be able to access the login and the register route whether it's logged in or it's not logged in that doesn't matter that one is not a pro seed route so we're going to check for that so we just say exclamation mark open our um array brackets and we say login and register that includes urlp name so what this is doing is checking whether the login and the register route is we are currently in any of this routes that basically what this is saying checking whether we are currently in the login or the register route so I checking that we are not in any of this routes with the exclamation mark in front of it by saying that we are not in any of this routes the user is undefined and the path name starts with Slash so by doing this we can check that okay if the user is undefined we don't want the user to be able to access protected route then in the Block in the in the actual if block the call it bra you can now say redirect and redirect will be imported from spel kit so if the auto input doesn't work you can come and type this out by yourself so we redirect the first thing will be the status code St code I'm going with is 303 and the second thing is going to be the routes that we want to um redirect them to in my case to be login route so let's go through this one more time this if block some people might not understand it or maybe I didn't explain it well so let's go through this again first of all in Lan man English what I'm checking for is if the route starts with Slash so every route that starts with Slash meaning every route except the login and the register route must be protected so in this application every route is protected except the login and the register route that's basically what this EV BL is doing is checking whether we are in any route so every route starts with Slash right every single route starts with Slash so we are in any route the user is not logged in and the user is currently not in the login page or register page so if that equates to true if all of this equates to true we redirect him to the login page because it shouldn't be on any other route if he is not logged in except the login page or the register page those are the two page that is allowed to be in so we would save this and now when we go to our our application we will notice that we probably been have been redirected to the login page and the reason for that is because of reload when we save this this is actually working in the browser and now we in the login page because of we are not actually logged in and we don't have any pocket based credentials or any valid pocket base credentials now that we are in the login page we can actually begin creating the login route first thing I will do is delete this about page we don't need this and secondly we create a login route now we can do this the same way we did the about route by creating it manually where you can see that that would easily and fast fastly get Z work C fastly no quickly quickly get stressful there is a nice extension that helps us called spell for vs code so I go to my extension tab I open this widely and I'll search for SP all right for some reason it's taking a long time to load but the extension is it's just called spell for vs code is the most installed SP extension in vs code look for it and you install it once you've installed it you'll be able to do nice things like this so let me show you reduce this and in the routes in the routes folder I'll just right click go to SP kit files and I'll say create route I'll name this login when I click enter I'll be able to choose from any of these special files that I have listed here once I have once here is the plus page. file and the plus page. server. CS file once I've clicked on those I will just click enter and just like that it's going to create that route for me a folder with those two special files inside them so I don't manually create them manually name them the first place that I'm going to go is the plus page that's felt for of the log route and in here I would remove this this thing here I remove this parts and I also remove this part here I don't I don't need those and after doing that I will go to the plus page. ser. CS file this file is the server file this is where we load data from the server using our load function and we submit data using our form actions so I'll remove this satisfi Parts I don't need this and the reason why I don't need this is because of I have the extension installed once the extension is installed it does the automatic typing for me so I don't need to import all those things but if you don't have the extension installed or you are not using visual studio codeing some other editor that does not have a spelled support then you have to leave those parts I'll save this and I'll go back to the plus page that for and before I continue I just want to do one little modification here now you see that I have this login directly in this route file and if I come here and I see each one this is the login page and I save that go back to my browser you see that now we're going to have this thing I refresh here okay sorry I CAU my time now so it's not the page is the application is not even loading anymore so I say PN pm I'll just run the Ser again [Music] 10m so I'll refresh this now we have this page and we see this is the login page look like we written it here what I want to do is do what is called route grouping so I want to group my routes so that it is more organized in this rout folder I'm going to create a new folder called but it's going to be in parenes so that's felt kit knows that this is just for grouping and should not affect the route so I'll just say open my parentheses I'll call this alt and then close the parenthesis and now I'll move this login inside this alt folder and now that login is in the out folder but you see that my normal routing is not stoed it's not like um sl/ login still the SL Lin and it still works the way I want it to work so in this alt folder I also have my register route there as well so that my routing is well arranged and is well organized I'll get rid of this part because of we moved it so it's through some inputs but I'll get rid of this and I'll save this now let's begin by creating the login form or the login page and all the things thats I'll remove this H1 and I'll create div tag in that div tag I have an H1 there and in this H1 I will say welcome like so and this is we have class and it's not like class name or class whatever just class just the same way we have the attribut in a normal HTML file class and in this class we have a couple of St util we say P1 p y be five that is sping top and bottom would be 20 pixels say text Center and let me save this so you can actually see what's happening text Center as you can see the text has moved to the center the welcome testt is now in the center I want to make that text larger so I'll say text to XEL and I also want to make the font larger so I'll say um font semibold save that you see we have welcome looking nice and after that welcome what I want to add here is the form that will actually accept my credentials and sends it to the pocket based back end so here I just comment here I say form now in s kits the way form works is actually very easy you can create a form set up a form action send the data from here to the form action and from the form action you take pocket base back end so it's actually relatively easy but we're going to be using tools that gives us even more power and makes the experience even better than the default that SP gives us so when using Chan felt it has a form [Music] component yeah let me show you real quick yeah form and in this form [Music] component it uses under the ud form snap and form snap uses under the ud s kit super forms so let me go to the website of both of these I'll say for SNAP no that should not be it like this so this is form snap on form snap is created by the same guy that created Shad CN SP and it forms can be a pain but they don't have to it's basically um rapper for spell kit super form as or component for spell kit super forms so now what is spell kit super forms Now spell kit let me just write super forms super forms. rock is basically what makes this whole thing happen so spelit performs is Tak Fel kit um forms to the next level adds validation adds a lot of cool stuff here so you can take your time here um when you do have time and you can read through the felt K super forms documentation so you understand better on how this works because of form snaps and chassan SP form components uses SP super forms under the Ood so using this library to actually create the forms and I'll show you how powerful these things can be but to actually use the form you're going to have to use the CLI to install it so you come here you copy the package manager that you're using I'm using pmpm if you're using npm you copy this and then you run it in your terminal and as I explained earlier I'm having issues with the CH felt CLI for some reason I'm not yet sure and I believe it's because of location if the support team for chassi and felt is watching this video please do help me check out what is going on but since I would not be able to use the C I'll be doing the manual installation which takes a bit of time because you have to install all the packages and then set them up but for you just use the CLI it should be an easy ad and once you use the CLI you will notice that in this lib components UI folder a form folder will be created there and in the form folder we have a bunch of components a bunch of Spell components that enables you use the form um component of Chan F we added in here so all you just have to do is run that c and it should work for you I'm going to pause this video now and I would manually copy those files and then I'll get back to you all right I'm back and now we can start building but before we actually write any code let's go to the ch C felt documentation and just take a look at how this form component would work so right here in this Anatomy they can see the way is actually going to work we're going to have this form tag and in the form tag we have this form field component and in the form field component we have this form control in the form control we have the form label which is optional and then any form input component and below the form control would have the form description and the form error this is a more explicit example that you can copy so what we do is we would copy this example go to our editor and we'll paste it so we remove this form part and just past this by pasting this we're going to have a lot of Errors happening because of first of all we don't have the um form being imported so let's import it go back to our chass and felt documentation and just look at how they import it so right here they import it as AIC from forms so just copy this the editor and above this one here would paste it there like this but that want draw away all the errors we still have the errors for the input we need to import the input as well and this form field is expecting this form right here so this form will be created for us with spel kit super forms but before we do anything further we need to return the form from the server and I'll show you what I mean by that so what you need to do is go to the plus page. server. CS file and in this file you're going to have to return the form so you need to have this function being exported from this file the name of the function must be load and it must be as synchronous so we come here to the r part and I'll just name this form and form would be await super validate and super valid will be gotten from spel kit super form and super validate we have to accept a schema at least it um expects one argument at least one argument and that argument has to be the form schema now beginning from spell kit super forms version two it accepts multiple validation libraries in the past it was just zld now you can use Joy you can use the other nion out there but the one that we would be using here is Zord and by using the SP kit or the sh CN felt C to install the form component you should have ADD sword installed for you but just so that you can be sure go to your package ofation file and you should see that Zord is installed here if it's not you can just manually install it and what we're going to do is create a schema now what we can do here is above this load function we can just write our Z schema but I won't be doing that I will be creating a file called schema so I'll say in my lips folder I would say schema. TS and in here I would create my login schema and all my other form schemas would be here so I'll just call this login schema so I'll export it out of this F for say export conss login schema would be equals to z. object now Z is going to be from Zod so we just import it here Z do object like this and in here the first field is going to be the email so we say email and email will be of type z. string and would also be of email as well because this is email so just say. email put the comma go below that and now have password and this will be of z. string as well and we want to add some constraints to this we want to say it must be a minimum of eight characters so the way I'll do that is by saying min8 like this I'll save this file I'll go back to my plus page CS file and in this super validator I'll put in my schema before putting in my schema I have to put in the adapter that I want to use I'm using the Zord adapter so I'll just write here Zord and I'll import Zord from CH from Su forms so I'll go up above here I'll say import Zod from s kit super phone SL adapters like this and in I'll put in my schema which was the schema and I import it from that file so just by doing this I have I am returning the form from the load functions and I can access the form in my plus page that's felt file here using this export Le data so let's continue below that export Le data I'll just initialize super forms here so I would say const form would be equals to super form from spell kit super forms and the first argument would be the form that I'm being I'm returning from the server which will be data do form now I can have options which I'm just going to set I'll set a value datas object here and I will say Zord clients cuz I'm using the Zord for my validation and I'll put in my login schema here so this is basically identical to what I was doing here but this is going to do server validation and this here we do client validation make sure that I imported this correctly yeah and now I can D structure from these forms some couple of things that I'll be using so I'll say cons object is equals to form and I can structure from the form um um form I can structure something called form but then this are the same name and this will cause errors so what I can do is rename this form to form data get the doar sign in front of it I rename it to form data and then I can also the structure enhance as well as Delay from it like this and as you can see all the errors have disappeared from this form now let me explain what's actually going on here and the form we having this method post which is necessary when using spell form actions and the post must be all in capital letter and then we having this use enhance which is enhancing this form for client side JavaScript so if there is no JavaScript available in the browser it would do a normal reload if there is it to prevent it from doing reloads so it makes it few more mod in and this use enhance must not must be from the felt skate super form because of um SP kit has its own enhance action so that's not one you'll be using in this case you'll be using the one from Super forms and this form field here is accepting this form and the form is accepting is not this one but this one above here so it's accepting the one used to initialize super form and in here you'll be the name of the um fi you want now in our schema we Define two Fields email and password so as you can see we have Auto completion one here is the email and after all of that we have the form control we have the label and you can put in the name email and under that we have the input and in this in we have this buy value form data and the reason why we have the dollar sign of the form data is because form data is store and then we say email because of it's the email field that we are working with here now if I save this and I check this out in the browser let me just make sure I save it and every other file that was unsaved so I'll say control K and then s I'll divide my screen and then I'll take a look at the browser now you see that we have this email field right here perfect what I'm going do next is just copy and paste this so we can have the password field as well and rename every instance of email to password that's just a quick way of moving so I rename email here email here email as well and I'll say password save that and what I need for this password in the input because of I don't want the password to be visible when the user is typing I'll just say type is equals to password like this and for the description I can get rid of it for both of them because we will not be adding any description so I can just get rid of the description here on the description here as well yeah we don't need the description but leave the errors cuz the errors are necessary give a better experience to the user now below the password field would have the button so would say um form dot button that mistake always happens so form button and in here would have a if block because want to shck for the delay store whether it's true or false if the delete store is true one show loading spinner if it's first want to show the login text so we say if and this is an if block like this say if dollar sign delayed again we want to Auto subscribe to it because it's a store delayed would show this loader loader two from lucid's felt and if you're wondering how you got lucid's felt well it's because of you use the CI to um initialize felt so if you initialize SP with CLI it would install new SE SP for you if you use the default team or the default style so you want to import this third one right this one says loore 2 you can rename this under this thing to something better if you don't like this but the reason why you want to import this third one is because of it gives you a better Dev experience and um V does not always have to optimize Those comp those um external icons over and over again which can lead to a bad de experience so I recommend using this third one here so because I don't like this oncore style I just like having two I can just screw up and then remove the underscore part and let's make that two like that and I can get this a class because of right now it's just going to be loading um icon it's not going to have any animation I can say size can say size six and size six is basically just a width and height of the same thing so it's going to be WID six height six and I can say animate spin like this and I can put my else here I can see else login like this save that and it will reflect in the browser very soon like that but this login button is a bit small it's not even a bit small it's actually very small what I can do is in the button itself give it a class and say we full cuz I want it to expand just like that and below the button I'll come here and I'll say div and in this div we have class so I'll say class N4 Flex item Center enter in that div I have another div and this div would have a class and this class is going to be Flex grow so what is going to be just one line so I say F's grow but t for b top and the but color should be gray gr 300 so say what g r e not ey 300 and outside of that div I have another div and this div is going to say all and in that that D is going to have a class I say mx4 text gr 500 and outside of that div we have a last div which is going to be identical to this div so we can just copy this and paste it down and when I save it you see the reason I was doing all that nice stuff was just to get this effect this slash or and then another slash just like that now if we take a look at this login screen it looks I would say terrible it's expands throughout the screen and doesn't look nice at all what I want it to do is to smaller like the WID should be smaller and it should be a bit like on the center of the screen is some something like that but I also want that effect for the register as well so instead of doing this twice like coming here and doing it giving this the class in this div and then giving it the class the same class to the um container of the register component as well I can what I can just do is create a layout here a layout in this art a group layout so that and I'll give the styles to that layout and then both of them will inherit that style so I'll come to this Al for file or folder and I'm creating file code plus layout do sp and now the component disappears because of it needs me to um it needs me to Output this somewhere output is children the way I do that is by writing slots so I'll just say slot like this and if I save that it should come back to senses and what I want to do is to cover this slot with a div and I give that div the classes I was talking about so that both the register and the login component to inity class I'll just say maximum WID to LG and the width should be full and if I save that you see that it's has gotten smaller the WID of the form page has gotten smaller I want this to be in the middle of the screen so I can see MX A2 when I save that it's going to take you to the middle of the screen and I can say shadow LG give it some Shadow and I'll say border give you some border and let's go with rounded MD make Le be rounded and give it padding it doesn't look nice now let's give it a pading ping all round of 10 and now it's get it's coming together I say Ming top cuz I want to give a little bit of space mty 20 all right and just imine bottom 10 like this now if I just save everything correctly and check this uh this looks a lot better looks far more better right let's continue so under right under this um div that we created for this all part I want write under this have another button that's going to be reting them to the register page what I can do is copy this button here come under here paste it remove all of these and just write register but I don't want it to be the same variant I can give this a variant and say um let's go with ghosts no let's go with secondary secondary it and now it looks different and not just that because of I want this to be a link at the end of the day I can say isre directly here isre and I'll link this to the register page so register now if I click this I actually go to the register route but we don't have register page yet so there don't need to click that but let's actually hook this up to our pocket base back end because right now we just have the form we don't actually have a form action before we do that go back to the page what I want to do is just add an action here so the action is going to be where we're going to be sending it to but since this is going to be just root it's going to be on the same page it's going to be on the same level as the action is going to be in there's no need for adding the action but I always feel like it's necessary to add it to prevent any error or issues so just say action will be equals to now the page where the action exist is where you the route is what you put here and for our case is going to be the login page because of the action is going to exist on this Plus page. Ts file and in the plus page the Cs file is belongs in this login route that's why I put in the login here so I'll go inside our plus page sercs and I'll create our form actions here the way form actions works is actually very simple just need to export an object called action so we will say export const actions is equal to this and instead of writing all this over even though that well plate code is actually very very small we can just use our um extension that I asked you to install the SP for vs extension so we can actually just get that by writing kit action so if I write kit actions I'll get a code written for me but then I get this extra thing that I don't need but okay and in here I'll create a default action so there are two types of actions there's a default actions and there's a named action one I'll be using here is a default action so I'll say default and sync output and a synchronous function here and this is synchronous function I'll get the events here and in here I'll say I the structure from the events I'll say const calibra is equals to event and from the event I'll get local and from local I'll get PB just remember we added PB to Lookout and that all I'm going to get there so I'll come under the event and I'll initialize spell kit form actions I mean spell kit super forms by saying cons form is equals to A we super validate remember we've already imported super validate and in here I the first argument would be event the second one would be our schema I using the Zord adapter so I'll say Zod and inside there I put my schema I'll say login schema like that now after that I'll come under there and I'll say I want to check whether it's actually the form is actually valid so I'll say if exclamation mark form dot valid meaning that if this actually results to false if the form is not valid I just want to return them a fil so I say return fil and fil is going to be from spel kit so I'll just import F so if it didn't did not Auto UT for you you can just type it out this is the input here so I'll say F and in fill the first thing is going to be the status code I'll say 400 sorry 400 second thing is going to be an options and I'll just return the form this form right here and after that if so this is going to return this if it failed but if it's it actually valid then I want to actually try to log in into my pocket base back end I want to see my try cash block here and in the try I'll say I'll wait PB do collection The Collection I'm targeting is the user users collection and I'll say Alt with password object the out with password method and the out password method is going to accept username or email and a password with options which you want to add options the on I'm going to be adding is the email and the password so we say form do data. email the second one is going to be the password we say film. data dot password like this and if there was an error comes to our cash block and we say cons we'll first turn this error to E I don't like having error say const the structure status from e but then e okay not going to be from sorry equal equals to e but then e does not actually know that status exist in it so we just say as client response error and this is going to be from pocket base so we can just click here and to import it for us and if the auto input didn't work for you again you can just write this out import Ty client response error from pocket base and now what we can do is return message and message going to be from spell kit to forms the first argument is the form while the second one is an option and we say the first one here we say status status and the second one is going to be the message um text so just say message and and just let just say an error or code like this save this and all should be well and good now so we can just and S save this properly and that's not just all after the try and the cash block they're going to redirect remember redirect is gotten from SP kit again so we just import that the first argument for redirect is the status code we say 303 the second is the route and we just say slash for the homage and you don't want to put the redir in the tribe and cash blog because if you put this rir in this try block it will be CAU by the cash block so you want to put this after you finish the try and cash block it will only get here if the try was successful if the cash was the one that ran it's going to return this message and it w get to this part of the code so we'll just save that and now we can actually test test our code and check if it would actually work but before we can test it remember we don't have any user yet so we going have to create one user manually with the pocket Bas um admin so I can come to my admin in the users collection click on create or new record button leave the ID empty the username leave it empty the email just add the email you want to use I'm just going to add my email at gmail.com add a password confirm the password verify wherever you don't actually need all these other field they not required but you can just type in your name you can leave the Avatar can click create now that you've created this one user you can now test with that user whether this would work I can come into my email and I can say gmail.com and for my password I can say just type in my password that I actually used to create this user and I'll click on login and see loads and seems like and it worked so it load it was successful authenticated us and we were redirected to the um the homepage so now we know that that works we can go back and we can move on to creating the register page what I'm going to do now is open my File Explorer B and I'm going to use the extension to create this route so I'll come to the alt folder right click spells with files create routes register now select the plus page that's SP file and the plus page that's TS file click enter and both them should be created now one smart thing that I can do is go to the plus page that's spy of the login page and I can just copy everything here contr a then control C and go back to my register route and paste everything there and what I can do now just edit this to fit the register um page I can change this from welcome to sign up or register which number one you like and I can change this action from login to register and I also want to change the schema from login schema to the registered schema so I'll go to my schema file here and I export another schema which should be the register schema I'll say export con register okay con and register should not be together register schema equals to z. object like so my first field is going to be the first name so I'll say first name that's not to spell first name and first name would be Z do string and a minimum character of three second one will be last name I'll just say Z do string as well minimum character or three as well third one be the email say Z do string [Music] and do email next one would be password I'm that so say Z do string and minimum of eight next one would be confirm password but what we're going to call it is password confirm and the reason for that I'll show you later on but you're going to call it password confirm and I'll say Z do string and this is just going to be like so Z the string and after this object here just going to put dot refine and here we can get the data and create our function here we can check for the password and confirm on the password confirm to make sure that they exactly the same thing so I can see data dot password and be equals to so 3 equals to for comparison so see data dot password confirm and we can create our options here and say message message would be passord do not match password do not match and the part would be just open your array and put in password confirm like this save this and go back to your plus page. spell file for your register route and change every instance of login schema to register schema and like this all right so this register is not actually spelled correctly it's supposed to be g i s I say g i s g i s so and now in this register um in this register form need to add more fields we have the email we have the password and we need more so I'll just copy the one of the password I'll place it under it and here will be confirm password or password confirm if you remember so say password confirm like this and I'll copy this paste this here for the label for it to be more user friendly we say confirm password not password confirm I say confirm password save that and under this password confirm I open div here and in this div I have my first name and my last name let me divide my screen so that we can actually be seeing it as we are making it so I'll save my editor and I will click on this register route so when we get this register rout we get this internal error and that should be because of we are not actually returning isa. form from the server so let's just copy this load function here and all the inputs just copy the load function all the input for the plus page do SS on the login and place it in the one for the register we have this on the lines because we're not actually using all these things but yeah can go back to the plus page yeah and saved everything but my error still persist and the reason for my error persisting is I have the script down script tag under here I didn't actually just copy over it I copied above it I pasted above it I thought I pasted onto it but now since I've gotten rid of that I can save this and the error should clear now we have the sign up page showing and we can continue so inside that d I have two FS but this div would have some Styles so we just open this div and say class and this D would be a grid container so we say grid and grid Co two and GAP five now we can copy this Fields here copy the first field we want to change the name from password confirm to first name and you also want to be careful because now we have this type of password we get rid of this type of password and for the form dater you want to put in first name there as well and the reason why we having this red line showing is because of in our. ser. CS file we're actually using the login schema not the register schema so we can just see G schema save that go back to our Plus the file and the error should disappear so so we can say first name like this and we change the label as well first name see first name and we can just copy this and do it for the last name here as well so I just copy this and paste it as a symboling make that F capital letter and yeah I'll just convert every part of first name to last name I say last name now capture letter last name like that I'll change this first to last save that and should have first name and last name right at the side like this perfect this is what I want now let's switch this login to register and this register to login so we change this login here we say register and for this register here we say login and for the text we also say log in save that and it should swap bam let's make this our Capal later as well feel a lot better now let's create the form actions for this remember just like the same way we created the form actions for the login page we create the form actions very similar way for the register page and I'm be using the default actions here as well so we can just say export remember I'm using my extension I forgot I say kit actions get of this actions part and in here I'll say default and I want an as synchronous Arrow function say sync like so and here I'll get the event and outside there I will structure from the event equals to structure locals and from locals are the structure PB like that oops so just like that I the structure PB and I'll say const form will be equals to a weight super validate first argument will be the event second agreement will be the schema so I'll say Zord Open Bracket and say Rister schema under that I would have my if exclamation mark form. valid and if it's not valid I say return F and really have feel we imported already so now have to import it again first argument will be the status code I say 400 and the second one will be the options for the form and I'll just return the form like that like so after the E block I have my try and catch say try catch I get my extension to Auto po that for me and I say in my try block I'll just say iwait PB Dot collection and the collection we are targeting again is the users collection I'll use the create method create and in here I'll just post in the form dot data just like this and the reason why I told you to name the schema of that um register that particular schema I told you to name it password confirm is because of spell kit I mean pocket base would accept that directly so if you name it confirm password we have to come here and then rename it password confirm and then send it to pocket base so the field and the field pocket base is expecting is called password confirm so just make our life easier name the that and we can just pop this form the data directly inside here we don't have to do any other work from that and just like the same way we had the catch block for the login route same have the cash block for this and instead of rewriting this I can just copy that again in you can do the same as well copy the cas block paste it and after the cash block we want to redirect this to a page and with pocket base when you register you're going to have to log in again at least that is how this application is set up so when you register I'm going to redirect you to the login page after that I'll just say redirect remember redirect is already um imported and the first um argument is it status code which for our case is 303 and the second one is the is the route so we say login like this save this and if we try this now this actually won't not work or it w work it won't work as we expected it to work because of we adding two extra Fields here namely the first name and the last name but if you check our pocket base admin you notice that we don't have and if you call first name and last name in this users collection we only have username and name don't have first name and last name but in our case we want the first name and last name so what we can do is edit this so you see this edit collection two tip showing here and this settings icon click on it and in here you can add and remove Fields so what I'll do is remove this name field so I can click on the settings part here click on this little icon and I click on remove for the same thing for the Avatar as well come down here click on this little icon here and click on remove as well so any fer I'm not using I want to remove them so I've removed both of those and I would click on New Field and this new field part I will click on PL text and I'll name this first name it must be the exact name that I gave it in my schema and I'll click on this new field again plain text and I'll say last name as well and I can give this some reject patterns and some constraints I can say minimum we if you remember the minimum we we used was um three for the first name so I can say three or I can just say non empty but in this case in this case we want exactly three so we say three and we can leave the max empty and for the last name as well we can say three and I would save changes this and it says blah blah blah confirm and now we have first name and last name added and we can actually test this out before you test it out make sure that you saved not just this file but every other file so by typing crol K and then s you would save every unsaved file in Visual Studio code go back to our application the sign up page and let's sign up so use a different email because if we use the same email it will throw an error for us so we would say 010 gmail.com password will say first name would be laal last name would beola I click on register and if that's successful we should get redirected to the login page and it seems like it was successful and I don't want to save this out click on never it was successful and it Reed us to the login page and in here we can now log with those scint shs I see at gmail.com I say password be and I'll click on login and now I'm redirected to the Ownage so we've successfully added authentication to the application and the next part would be us actually creating the dashboard itself so stay tuned let's move on the next thing that I want you to do is to come out of this alt folder and in the root layout we are going to add some UI that I want to persist throughout the application namely the N bar and the Side Bar so let me show you how the structure would look like above right above here would have enough bar how me I mean na bar I mean an ed so I'll say na bar and as the side of the W screen would have a sidebar something like this so This Side Bar will be at the side what the n Bar will be the other I will create both those components but first let's actually put out the structure so I will say a div and I'll pop my slot inside that div and I'll give this div some class say I'll just say I full for this div this is the container div and inside that div I have another div this div will have class as well and I'll give this an height of 80 pixels now say padding left of 56 but I want this pad to only take effect when we are on medium to large screen so I'll say MD in front of it like this and I'll give it a position of fixed and I'll say insert insert y z we of full and Zed index 50 and in here is where we have the N bar so I put my comment here say n Bar below that outside of the div covering the nve bar I come out and I'll say div another div and in here I'll pop the sidebar and the D covering the sidebar would have classes as well I'll just say class and I'll say eding so this eding means the that I want it to not be visible but I only want it to not be visible until we get to the medium size of the screen so once you get to the medium size of the screen it will be Flex display flex and that means it's going to overwrite the style of display um hiden and or display none rather and we can now say it full with 56 Flex of no that's not spell Flex Flex Co and fixed this insert y z as well and Z index of 50 as well and for this slot we pop this slot in a main container and give this class as well so say from medium to large screen I want to give this a padding left of 56 and the reason why we are seeing we are using this exact value is because the sidebar is going to have a width of 56 and we want the sidebar to be on the left hand side and after the side barar is when we want to be seeing every other thing we don't want this thing to be inside the part of the sidebar that's why we are giving this this exact value and I'll say padding top of 80 pixels and the reason why I using a padding top of 80 pixels here is because of the other as you seeing here has an height of 80 pixels and I'll say height of full now let's start off by creating the Nar component so you open your Explorer go to the leap folder in the leap folder you come to the components folder and in the component folder you would create the component inside here you try to avoid putting anything in this UI folder leave this UI folder for chassi and Sal so we'll put the components we want to create in this components folder directly in the components folder so I'll just click here on this component folder and I'll click new file and I'll say n Bar do sp like so and in here we want to put our script tag and say that our script tag is of type is of language TS outside of that we have a d this div we have this uh class and we say P4 border sorry B so just say but bottom and let's divide our screen as this time so you can actually see this reflect on the browser so now you see that we have this page our own page nting the styles that we put in the layout and you notice that it now has this padding and this margin at the top because of at the top want to pop in the nav bar and if I go full screen see it also has the padding or the margin on the left hand side and that's because on the left hand we want to pop in the Side Bar that's why we put the margin on the top and the margin on the left but when we go to a smaller size screen the margin on the left disappears because remember if you go back to the layout you'll see that I said the pattern on the left should only starts from the medium size screen to larger screens so it only starts from the MD size that's why it's it's not going to show on smaller screens so let's go back to the nve bar and continue let's import the N bar now in the layout so I can just remove this part I have KN bar comment and I can say n Bar and I'll just import this like so go back and I'll continue save that and I continue wring out the Styles I can give this an i of full so I want to take the full height that was allocated to it and I'll make this a flex container so I'll say flex and item Center I say BG background and Shadow SM and if I save that you will see that this little thing we have here that has a border yeah with a little sh just yeah just has a border it will take the full height of this thing and it will have a shadow so once I save this see what happens it takes the full height and it has Shadow now that we've done that I I order the components here I'll call it Navar route and I'll create a component in my components folder I'll call it nav bar rout do spelt and I'll pop in the St code as usual and in this div I'll give you some classes first I'll make this a flex container so I'll say flex and I'll say Gap X2 and ml Oro and in that D I'll pop in a button and you should have the button already installed or copied for you when you added the form but if for some reason it wasn't or I'm wrong then you should just go CH and documentation go to the button section and copy the CLI on copying the button into your application or your project so I'll just write here button with cap to letter b and close this and I also want to import that button here so I'll just say cni I button and to import the button for me and inside this button I'll just have this logout logout icon this logout icon is going to be from Lucid SP and again because of I want that one with Slash icons you can just copy let's say this one and then from the luces felt part you can just go slash icons slash log out and then remove the qu braises and you can use this like so you save this you will see that we having red lines here indicating errors and that's because this log out here is wrong what you want to write is log out like that now you save that the ER should go away and we can go back to our have b f and we can import the N bar here bar I can save everything by typing control KS now all the files should be saved going back to my na bar rout and I after this logout icon I'll just say exit exit and then in this button itself I would give it a hre slash and a size of SM and the variant of ghost once I save that you'll see that this button right here will change it would have this exit I um text there and it would have the icon and it will be variant of ghost just like the way I said it and now after this button you want to put an avatar so you're going to go to the Chan felt documentation again go to the Avatar page copy the C to install the Avatar Into Your component and install it once it's installed you can come back and continue I have installed all the components that I need manually so I don't have to actually pause the video every time and then install it again so I can now see avat and what you can also do is install the chassan felt vs code extension so you can use nice M things like this so I can now say cnx Avatar and by doing that it pops out this code for me for the Avatar component and now it wants me to import the Avatar so I can also come above here and I can say cni Avatar and need to import the avatar for me as well now you can change this GitHub part to just change to your GitHub name I'll say speed.png like this and the out I'll say sped I'll just leave everything as it is and I'll save once I save the Avatar should pop up like that and I probably change the C to La cuz that's my initials nice after that the last thing is I want to pop in a logout button so say button once more and I'll just say log out say size SM type of submit and because I want to use form actions for this for this particular action I'll pop this button inside of form tag so form and I'll pop this button inside and this form would have a method and the method would be post again all in capital letter and the action would be a named action this time remember the last two times we use actions we use default action now I'll show you how to use named action we already have action here so we can just get rid of this one actually and way named action works first of all is the route you want to go to the route I want to go to is the SL route and then you put your question mark and then put the name of the action which in our case is log out just like that save this and now let's create that for action open your Explorer out of the components to the route and in the route you want to create a plus page. CS for the root plus page that's F say plus page TS and in here I'll just say kit actions like that get R of this actions spots and remember the name of the action was log out so that will be the name this time not default but log out and this will be an synchronous Arrow function here and in here we get event and we can D structure from event remember Lookout equals to sorry that was a typo we can't structure event from event well locals and from locals you can D structure PB come out of that and now I can say PB dot out do clear the clear method like that and this is how would log out our user I can go back to my Navar route double check this just make sure that everything was written properly and it was now we actually done with the nav bar route what we going to do is go back to the nav bar and in this nav bar we have another component here which is the mobile sidebar because we want a little icon here that when we click on it be to open the side barar only when we are on the mobile screen so I'll call this mobile sidebar and I'll create a component for that move B sign bar do s then and this I'll get of this de I don't need this de what I need is the sheet components from chass and here so again you know the drill I have already installed it because of I'm using manual installation all you have to do is go to the sh F documentation and go to the sheets page copy the CLI install it in your run it in your terminal it will install it copy it into your code base and you can continue so right here I'll just use my extension again cnx sheets you should pop out the sheet component for me and I just need to um import it so cni I sheets I don't actually need to put just sheets here and here I'm going to remove some things that I don't need for example I don't need this title or the description I don't need the Eder as well so I just copy everything inside the Eder and the Eder itself and remove it for this trigger won't have an open but we have an icon so the icon will be the menu icon and this will be from lucid's Fault now you can go ahead and do the slash icons SL menu if you want but you can also leave it this way if you prefer I'll be leaving it this way from now on just so I can make development faster but I just decided to show you that pattern so that you can get a better developer experience when using CH F in this content or before we get to this content we're going to add some classes to the trigger so just come to Trier and say class and I say MD eing because I want this only be visible on mobile screens I say pr4 over we have an opacity of let's say 75 and I'll put a trans yeah and for the sheet container itself I'll say class mding as well P0 BG background and I'll give this a side side of left let's save that go back to our Navar and in this comment import the mobile Side Bar save this properly you should see it pop up right here and when I over it you see that we have this little opacity and when I click on it we have this sheet open so that's what I want now going back to the mobile sidebar in the content Parts I want to actually put something in here what I'll put here would be the sidebar components so I will just comment here as well and say sidebar save that and move outside back to my root layout because I will not also I will not only be putting the sideb here I also putting the sideb here so in here I'm going to create the sideb component as well I would open my Explorer to my component and I'll create a side by component and in the div the container div I'll get this some taing classes first one be right full border right make this a flex container a flex colum overflow y Auto makes of B G background and Shadow SM in here I'll have another div and this div would have a padding no class first of all then P 6 inside we have here we have the logo now if you have any image if you want to add you can add it here just say logo yeah that's my logo that's my own logo and I would say under that div and this div would have class now put flex and flex Co then weight F and inste that the yeah I have another component called the sideb route say Side Bar browse now we have the sidebar comp created we can import it and place them wherever we need to place them first of all we need to put it here so I'll say Side Bar and second place that we need it would be in the mobile sidebar and in the sheet content I'll say Side Bar as well now if I save everything control K and then s and I click on this icon you see we have this logo part at the top here and if I go full screen that icon should disappear and I should just have it displaying by default on my left hand side let's go back to the sidebar and remember we have this um sidebar route components to create so let's create that now open your components in the components folder create a new file called size by routes routes do spel and in script tag here we create an array and we call it routes so cons rout will be equals to an array and this this AR is going to be an array of objects first item here will be icon the icon and then let's say list list will be from Lucid SPS second one will be label and the label will be the name you say CES third one would be the H and we say slash teacher slash courses and we can just copy this and paste this and just rename the things that we need to rename second one will be bot the LI will be analytics and the HF would be instead of CES to be Analytics sorry and I'll save that and in my div I just want to Loop over this route array before that doing that I in this div I'll give this some classes so I make this a flex container I this to be Flex colum and a weight of f so in here I'll just put my each block since I want to look through something and I'll say each route as and then I can the structure out of routes the is ref the icon and the label and inside here I'll put another component called sidebar item so I can just comment here Side Bar item and I save this now I would go back to where I need to pop in the sidebar route which is inside our sidebar components and I'll pop in the sidebar route component I'll save that I'll save every other file with control key and then s make sure everything is saved and when I open my sideb once more you see that it's just the same thing and that because in this side bar routes we're not actually outputting anything it's actually empty but if I outputed the liell so I put a p here and I Calles and I said liel save that you see that the label of each of them will be outputed now we have course and we have analytics so it's working just just we want it I will save that remove that and let's move on let's create the sidebar item component my component folder name this sidebar item do felt and I do my little emit stuff sfc this div I'll turn this div to an a tag and this a tag will have hre and this H is going to actually be props so we're going to be getting the H from outside this component so I'll just say export let H ref and it should be a type string and instead of going here and saying hre is equals to hre what I can do is since it's the same name the same the name of the prop is the same name as that of the attributes I can just say craes h and pop it in like that now let's add some classes to this a tag but we want to add some conditional classes to this um it tag and if you use the CLI for CH F to install your component or to set up chassan felt to initialize chassan felt you will have installed something called clsx and in your U file so let me go to my you file you will have uh a code cre um generated for you called CN so this is just an helper function that mixes just basically mixes tailing Mudge and CSX so their functionality are now bed together in this one um function so we can use that function to add conditional classes the way we go about it is we're going to open our col here and then we'll import that CN function that has been exported from that folder so we just say CN and it should be imported from li/ and in that CN we open our brackets and we can pop our Styles here this are going to be the base Styles so we can just pop in the Bas style I'll say Flex item Center Gap X2 text M foreground text SM font medium pl6 transition all and when we over it I want some Styles I'll say over and then text slit I change color over it slit 600 and I also want to add over for the background as well so I say over BG muted now these are the base Styles I've just added let me make this my full screen so that you can actually see what's happening see to break it now I've added the base style now next I want to add now is the style that will be applied based on if a particular value is true or false now I can write after the base sty C comma open my qu brazes this string here is where I put the Styles and here is where I'll put the value that I'm checking on for truth or false and it's going to be something called is active and it's active will create right here we say dollar sign because this is a reactive variable so say dollar sign is active would be equals to okay so we want to get P name and the way we do p name is we'll get it from the page store so I would say dollar sign above that is active I say dollar sign part name is equals to dollar sign page because page is a store and be imported from App / store so I'll say page do URL dot P name and I can go back to that exactive that we were just declaring and I'll say exactive is equals to path name now I checking if the path name is equals to slash and href is equals to slash as well or part name is equals to hre or sorry or part name dot start S and we put this like so H ref with a slash at the end and we can save this that's just what we're checking for we're checking for if the B name is equals to slash and the ISS is equals to slash so if this is true this exactive would be true or if part name is the same as HW if that is true then ex active will be true or if part name starts with hwf and if that is true is active would also be true now we can pop in the Styles we want if is active is true I'll say text primary and BG primary as well but I want to add some opacity to this I'll say slash 20 and over B primary sl20 as well and over for the text as we say text primary and I have two columns here all like this I can save this and all is well now inside the a tag I would have a div and this div would have a class so let's just pop class and it be a flex container so I'll say flex and then we want item Center Gap x 2 and py 4 and in there I want to puts in a icon well a dynamic component actually and where we do that in Sp is by using this spelt component tag the special tag called spelt component so I'll say spelt column component and in here we have to put the value of this so I'll say this and this will be equals to I ion an icon will be gotten from outside this component as well so I'll just say export let icon an icon will be a type of component type icon and component type is going to be from spel so we're going to import from spel I'll say component type that's going to be imported from spell and we can pop in here the type that we want which is icon and icon is going to be a type from the seat spell because the type of icons we'll be using are from Luis F now that we've done that we can pop in some classes here as well so I'll say class and I also want to have some dynamically added classes here as well based on some condition so what I can do is use the CN as well so craes CN open my parenthesis add my base style which is text muted foreground like so and then come over out out of that open my colleag brazes say text primary and this will be active if is active is equals to true and I also want to add the size for this icon component so I will say size will be equals to 22 and size can actually be a string so actually it has to be a number so change that to 22 and inside of this components we can pop in the label I mean out side of this component I mean so we need to make this a self closing tag so I can remove this and I can put slash here to make this a self closing element cuz we don't need to put any children inside inside the div outside of this felt component tag will pop in the label and label again is going to be a prop as well so I'll just say X Sport let liel and label will be a typee of string after we've added the label prop we can come down outside of this div as well and create another div and this div would have class I'm going to use CN here as well so call itra CN and the first thing we add will be the base style I'll say ml AO opacity zero border two border primary onight a f and a transition all and I want this to actually be visible when this active is true so I'll add my call here and I'll say the opacity should be 100 when is active is true I'll save that and since we don't have any child for this div as well we can make this a self closing tag so remove down then put slash right like this and save okay now let's use this Side Bar item component in the sidebar route when we need it so I can come here and I will say sidebar item like this and this is expecting some props so there will be some errors some red lines showing and what we can do is popping all the props that we need we can see is ref just like this since they are the same name icon just like that since is the same name and Lael just like so I'll save all the on saved files by typing control KS and I will divide my screen so that we can see the browser now let's check what and how it reflect in our sidebar I'll click on this icon but one other thing that we can do is if you remember we have the sideb showing by default on the full screen so we can just go full screen but since we need to divide our screen because I don't want to be always clicking on this icon to see what's going on in the sidebar I want this to show me what is showing on the full screen I can just reduce my browser's size to 80% and now we can see the sidebar now we can see we have cost with the icon analytics with the icon and if I added more it will reflect I can copy here see comma paste this comma paste this comma P this save this and we should see like three more analytics pop up and just as I set more analytics have popped up we don't need all those and get rid of them save so let's move on to actually creating the store page but before I do that I want to show you guys something if I go to my login page right now so if I go SL login You' see that we have the Ed and the sidebar persisting and the login layout as well we don't want to see the Eder and the sidebar in the login and the register page so what can we do about this well the reason why it's actually showing up in the first place makes sense because we have those components in the root layout and so since it's on the root layout or in the root layout it would prist for every single page in this application in order to prevent that we can do things called group layout so right here that's actually what we're doing here we have in this alt and this bracket alt we're having this group layout of this alt folder has this layout for itself what we can do is create another thing similar to that but for the dashboard so I'll say dashboard remember to put this in parenthesis and I will throw in this plus page do felt in there the plus page do layout D plus layout does felt the plus page do Ser do CS as well inside here and now you see that we're having a bunch of Errors just ignore them for the meantime the other thing I want you to do is that and at the end of the day I want to ro layout for where I can put my Styles and my fonts that prist throughout but in ter of the UI I don't want it to prist throughout the application so I create another root layout outside of the dashboard so I'll say layout do spelt and I'll basically copy all that I had here before all of this here I'll copy this and I'll paste this here and I'll save I'll go back to that layout inside my dashboard fold down now and I'll get rid of these two inputs at the top here CSS and the font input now going back to the root layout I leave these two inputs here because we need them at the root layout we want them prist throughout our application but what we don't want to Pro throughout the application is the nav bar and the Side Bar so I'll get rid of those and we don't need a lot of this code I'll get rid of those as well and I'll just put a main tag and in that main tag would have the slot outed there this me tag will just have a class of he screen and just like that we save this and save every other file so we say control k then s and now you see the login page does not have those Styles but when I log in to my application let's see whether or not the root page on the other routes will have this St and log in and as you can see the base route as the style has the sidebar as the other and every other route that I put inside this dashboard with other routes every route I put in this alt folder would not have that style this is what they called group layout so each of this group have a different layout now let's create the teacher page so come to your dashboard in the dashboard I'll just use my extension cre route I'll call this teacher and in teacher I'll get the plus P that's SP on the plus PCS enter in the plus P ser. CS file I'll gr of all this code I don't need I'll get rid of this and I'll also get rid of the return as well because of what I want to do here to just redirect them somewhere else so every time they come to the teacher route so if they go to local 5173 teer I want to redirect them to Local 5173 teacher/ courses because this teacher route is just going to be some sort of Route representation so there's not going to be any UI in this Cher route it's just going to be something that we have in the URL so everything time they come to this route in particular we want to redirect them somewhere else because there's nothing for them to see here so I'll see redirect and redirect is going to be from spell pit first thing is the status code 303 the second thing is the r i see teacher/ courses now let's create a route inside this teacher route out say a new subet file create routes courses and I'll choose this and this and click enter I'll see here this is the courses page and I will get rid of all the code we don't need here and we can navigate to this route by just clicking on this course um Link in the sideb so click here and now I'm in the CES page and as you can see this is the cost page and as you can also see that my sideb is showing that the cost link is active now in here what I'm going to do is just have a div and that div would have a class of P6 and inside that div would have another div that div would also have class make this a flex container so I'll say flex and items Center py py4 and in here would have a button so the button is going to be from trans remember button and in this button I would have an icon the Plus Circle icon from the seats F so I can just import them by myself if you trust you could feeling to import it for me I would import the icon first I say import craes plus circle from Lucid with an e f sorry not slash but Dash this is fil and I also import the button I'll say cni let's say CN is going to work cni doesn't work we can just import the button usually so I'll say import button from dollar sign lib slash components slash button slash button dot SP and I'll save that and we have this error because of this plus icon is not closed so I'll close this before I save I'll give you some couple of classes so I'll say class is equals to size four margin right two and outside of that I'll say new course I'll just type out new R and this button would have an issf and it's going to be slash chacher slash create I just give it some class we say class margin left all to and that was wrong not equals to but Dash and now I can save this to see it show and now we have some errors here as well because of in my button input I don't have the UI folder here so I'll say slui before the first button I'll just say UI slash save that the error should disappear and we should have this new cost button showing up here if we click on this we'll be redirected to a page that is not created here so we have this not found error so let's quickly create that page so the page we want to create is this create page so it has to be in this teacher route so I come to my teacher rout and I'll say spell kit find file spell kit files create route the name is create and then here I'll choose the plus page F and plus page CS and inside this create you want to go to the plus page do felt of the create and remove all the unnecessary code you don't need we don't need this sorry just pop all this out here and pop this out as well okay let's start creating the UI I'll come outside of the script tag and I will say div and this div will have couple of T utility classes give this a maximum we of 5xl MX AO just be in the middle this a flex container same MD item Center I say MD justify let's go justify Center make an IT of full and a border give this a border and say P6 six like so and in this div we have another div and inside that div we have an H1 and this H one would have the text name your course let's save that so we can actually see this thing reflect in our browser let's give this H1 some Styles I'll give this a text of two Xcel make this sler now it's sler good under that we say P tag and this P tag would have the text what would you like to name your course you like to course and let's say don't worry you can change it later what am I typing you come on you can change it later and let's save that see the way that looks okay we CLE have mistakes here save I want to give that pag some classes as well doesn't look nice say class say text XM I'll say text muted foreground see that and yeah looks a lot better now after the P tag would have a form and this form would have an action direct into this route so it be chicha slash create and we have a method of post all in uper keys and we have class of space Y8 and margin top8 save that now let's pop in F kit super forms in here because of remember we're using spell super forms to undo our forms const form is equals to Super form that going to be from spell super forms first argument is going to be the form return from the server so say. form remember I return anything yet but we would do so very soon and I will see here validators would be Zord clients because we're using Zord and in here we pop in the schema right now we don't have the schema so let's create the schema go to your schema. CS file what we will do now is create the C schema I now say export export con cost schema would be equals to Z do objects the first the first field would be the title the title of course say Z do string dot minimum see do minimum would be one second would be the description see Z do [Music] string do okay let's just leave it as suchar let's not make the description required to create a c so say just like so thir one will be the image URL say Z do [Music] string dot optional this want to make optional then we say price is z dot since this is the price we don't actually want a string but a number we can say z. number and then we'll say dot optional and in the number in the number um Brack ET we can just open craes and say Co is equals would be true we say comma and then we say is published would be of Z do Boolean and lastly category would be Z do St do optional as well now for this form what we need is just the title so initially to create a course you initially just need a title the required fi to actually create a course is a title and the cost would be unpublished and to actually publish the C you going have to fill in the remaining Fields so what we can do here is say export const title schema is equals to C schema this C schema we just created do pick now we want to pick just the title and I will say in craes title is true now save that now that will saved that and saved every other unsaved file in our edit so we should see that the name your C stuff has gone to the middle the screen and going back to that page we can actually pop in schema right here the title schema in this Z clients so I say c scha pop that in and it's going to be imported by Visual Studio code oops look like it didn't work all right and we also have to import Z client as well so we import Z client and Z client is imported as well moving on we going to theu from the form a couple of things so I'll come under here I'll say cons call braces is equals to form and then from this craes I can get form again and since it's the same name remember we can just easily rename it so I'll call this form data put comma I will get the enhance so we'll enhance our form comma I'll get delayed for the loading spinner and this time I also get submitting so we can move inside our form here and say use in hands I will just say use and and like this and we can actually put in our field now so I'll just come here and since that field can be a little bit stressful to rewrite every time what I would do is go to the login page and I'll just copy one field there like just this one here copy go back to the page and I'll paste that and remember now we going to have to import the form so I'll use CN I form let's try this one more time all right so it doesn't import the form we can import this or just copy it from the page from the login page as well so I'll copy this as well as the form copy both of these move back and paste it there no problem and now in the part that we have email we want to say title and the remaining place we have the instance of email we want to change us to title I'll save this and just control key s to save every other unsaved file and now that I gone ahead and saved it it shows us this 500 internal error and that is probably likely because of dataform does not exist that was why I was trying to pre prevent saving this particular file but now let's actually go and return from from the server to get rid of this error now go to the Plus page. server. Ts file remove the code that I don't need get of this as well now I can just come to the return return say form would be a weight super validate that is from s k super forms and in here we put the Z adapter and in there we put the login the ti to schema sorry TI to schema that's not that's not how to spell schema tile schema now save that I'll go back to the plus page. spell file I see that the red arrow has going away and I'll just save every file and wait for this to reload now the arrow disappeared and we have our title field showing now for this we actually want a description so remember in the login register we didn't have a description because we didn't need a description but for this we want a description so I'll just say form dot description and in there I would write what would you teach in this cost save that and description should pop under there like so and we'll move under the form field open a div and this div will give this div a couple of classes I'll say um Flex item Center Gap X2 and inside the div I have a button button from Chan F and I'll just see if this can Auto inut for me yes it can and in the button I'll give before we go in the button let's give a variant of ghost and give this an isre of Slash and and let's give the button a text of cancel like so and outside the button we have another button but this time it's going to be a form button so we say form dot button and in here we'll put an if block so I'll say if and we are checking for the lead remember the lead is a store so we have to Auto subscribe subcribe to it with the dollar sign and inside there if the is true we want the loader two icon sorry I keep making that mistake and remember in order to make this actually spinning icon mod have to add T classes first of all I want to change the size so I'll say size and I'll give this six and I'll say animate spin here outside of that I'll now say else meaning if delay is false I will just say continue save that and see that reflect in the browser nicely all right let's move on and in the editor what I'm going to do is in this input I'll say simply should be disabled if submitting is true so just put sign submitting and the submitting is this one here so we can in fact just copy it and paste it directly here I'll save this now let's move on to actually creating the form action for this form go to the plus page Ser CS file and I'll write kit action get R of the code we don't need and we create a default action here YY I'll get event from here and I'll the structure from events look out so I'll say con craes is equals to event and from this craes I get locals and from locals the structure PB you should know the D by now and here I'll just say const form is equals to await super validate in here the first argument would be event the second would be the schema first of all we need to pop in our Zord adapter secondly we pop in the schema I say title schema and I to check if this form was invalid so I'll would say if exclamation mark form dot valid I'll return fil and fil will be from SP skit and the first argument is the status code which would be 400 in our case and then we return back the form and outside that if block then the rest of the code after this if block will run if the form was valid so I'll just say let cost record and cross record B of type record model and we can import record mod from pocket base and if the Auto Import not work for you again you can just pause the video here and type that out after that we open our try and catch block I'll say try catch bam like so in the try block I will now say cost record is equals to a wa PB dot collection want Target the c o ursc the CES so CRS the cses collection we not created the CES collection yet in Pocket B so we do that after we write this but let's continue and see dot create and this method will create a new record for us in the cost collection call is spread out the form do data and after that we just say user would be user. ID and the question you should be asking is where is user we didn't get user from anywhere well remember in our oops we actually passed user to local so we can get user from look house just way we get it from P so I can say comma and say user here now this on the line red on the line should go away and in the catch block where we catching the errors I'll just copy the same thing we have for the login page in the login form actions it's basically the same thing so it's doesn't make sense rewriting it over and over again I'll just copy this part I modify it as I will paste that I need to import client response error from pocket base and message from spel Super forms I will change this error to e the only thing I'll change here is since I'm returning this message I don't want to actually return status from here I'll add code the status myself so what I will say is from this place I can destruction error message from here so what I can destru from here is actually called message I'll just guess message but again this has the same name as message so I can rename message to error message so I say error message and I'll remove status as I said before I want to add code the status I want a status of 400 so I just get error message and I'll say comma error message and then comma and here I will just return this status at coded to 400 like that and if you come above this you see that this user is having a little bit of error saying it could be null or undefined we could put question mark in front of the dot and that on the line should disappear and outside of the cash block we can redirect the user remember you don't put the redirect inside the try block so this this redirect would only run if the try was successful first is the status code of 303 the second would be the route and I'll say Cher slash CES slash and we want to put in the course ID so what I'll do is change this to back TI and use my dollar sign craes and say cost recod do ID like this and this should work one thing I want to take notice of is that we are returning the this message to the client and what we can do is actually output this message anytime there is an error so I'll go back to my client go to my um plus page that's SP file and in here you see that we have this options part where we have this valid details we can actually add more options here so I can say unupdated I'll say on updated I don't want the unupdate I want the unupdated I'll open My Method here and I'll the structure from here form and in here I can put an if block I'll say if form Dot message open my block and I will now see if form do valid and this is not if get of that and I put exclamation mark in front of it because I to check if the form not valid was equals to false and here I would do something so what I want to do here is actually reveal a toast notification or show a to notification and if you go to this chassen F documentation you would notice that there's a page called soona in a component um sidebar you noce a page called soona and if you click on that you'll see this sunna tost notification components that we can use and as I said since I'm using the manual installation I have installed all the components that I need so I don't end up going back and forth and back and forth in manually copying this files so all you need to do just copy the CLI P it in your terminal and run it it would install the soona component into your application and every other dependences that it needs now here in the soona page you see this installation guide where they have the setup team support so let's read this by default soon will use this user system preference to determine whether to show the light or dark in I'm using dark team so every time I add soon it's automatically changed my um web page to dark team because of it's using my user preference for that so to get around this you can either pass a custom team prop to the component or simply use mode Watcher which you can add code a dark or light mode should you wish all you can do now is just I think the best way to go about this is to use mode Watcher you click on here so this will take you to the mod Watcher geub repository where you are shown how to install mode Watcher and how to use it so you pop it in in your root layout do felt file and in here this is what you want to do you want to just say default mode will be equals to light you don't use dark if you want to use dark you use dark but then you w follow along on this tutorial completely along with this tutorial well you can go for light here if it's giving you a dark te and you don't want to dark team you go for light here and that should fix your problem so going back you see that we have little errors here and that's because of I was using this format and if I was using this format what I have to do is make this an AR function I have to do this make this an AR function but since I don't want to do this I will have to remove this qual Braes I mean this columns here and I should fix it at the same time I can save that and the aror should disappear so quick update I just rechecked now and it seems like the chassan f C is working for me once more so we can actually go through the steps together now I'll just copy this for pnpm open up here and I'll P this in here I just type in y for yes and it's installing component components not already exist and this is because I already installed it manually before I just want going to show you how those steps would look now the next thing I'm going to do following the documentation is to pop this in our root layout so I'll copy that component go to the root layout and just above here I'll pop that in and I want to make sure that I import that as well and that we are good go back to the page and in here we can start using soona what I want to do here is show the return message in the toast so I would say toast and toast is going to be from spell sooner so I'll come above here and I'll say import toast from spelt soona like this and we can see tools do arrow and we open our parentheses and you just say form dot how many El am I going to write message think I'm starting to see double because of I don't know what I'm typing at this point okay once you save this and you open your browser you might notice some error the best way to get rid of this error is to cut your Dev server and run it again so I just cut mine with control C and then I press the top arrow button here and enter to rerun it now I'll refresh my browser and this is what I was talking about dark mode list in checking your system preference and using that as the team one way of doing this is going to your Dev tools we go to local storage and here we see modood Watcher mode we can change this manually to light and that would fix it and the other way of doing this is the same way they said in the documentation is to add code it in layout so I go to our root layout above here I will import mod Watcher and I'll just see theault mode would be light now before we leave this page I also want to add some things to this toar some more things this toer I'll say Rich colors because I want to see different colors like if I said error I want to see a red error if I say sucess I want to see the green color and I'll put a close button because I want the close button and I'll just say team is equals to light now I don't need to do this anymore but I'll just do this just in case I'll save that and I'll go back to the plush page that's f f and now if there was an error this tost would show so now let's try to create a course and see what happens we should you save everything control k s open the browser let's write our title when we click continue if this redirects us to a not found page then that means it was successful so let's see my first course and it says this request resource was in that was the eror we got and the reason why we got this error is because of in the pocket based admin dashboard we actually haven't created this collection called courses so that's the next thing that we're going to do now so go to your pocket based admin dashboard in this you see this button here says new collection click on it and name this courses now let's start in the fields first field here is going to be the ti two that's what we're working with right now I'll call this PL text I'll say title and we can give this a minimum length of three and the next field here is going to be the description also plain text description this won't have any constraints the next field here would be the user and the user is going to be a relation so click on this relation and we say user and we select the collection we want this to be relation to and we will select the users's collection next one here and we also need to make sure this user is actually ped so we say C delete we say casket delet should be true and we'll click on non empty and we'll click on we click on this new field again and we'll add the image URL and the image URL will be a type of file so we say file I call this image URL and we just click on this settings buttons one more and here we can add like a maximum file size we will simply leave this as it is what we want is the allowed meme type on mine so what we'll do here is just select only the ones that are image but instead of selecting them one by one what I will do here is choose preset and go for image and we click on the new field and this time we choose number cuz this going to be the price click on New Field and here it's going to be is published and is published would be type of bulling and New Field lastly the category and the category is going to be a type of relation so click on relation and we say category and we select collections now we can actually select any collection for the category because we don't have the category collection yet or we'll leave this and we'll click on Create and you see as we clicked on create it gives us an error that because we need to add a relation so let's use user um collections as relation for now so we can actually create this category we edit that later now let's create the categories collection so I click on new collection I name this categories and I give this some Fields the first field will be a PL text and I'll call this name the second field would be a relation to the cost so I'll say CES and this can have multiple courses so one category can be related to multiple courses but a course can only be related to one category so I'll just choose courses here and this single here I'll choose multiple and I would create now I'm going to start creating new records here because of I create all the categories here from this dashboard directly so I'll click on new record I'll leave the ID empty so it autog generates from me I'll come to the name and I'll say flaming and I just leave the course empty and create and now that new record button has disappeared but we have it up here as well so I click on new records again go to the name engine nearing and now click on create click on new record again accounting this time create new record photography create new record Fitness create new record music create new record computer science create and that's all the category that would be needing so I'll go back to the course because I want to change the relation that the category has I'll click on this settings to edit collection and I'll scroll down to this category here and I would come here to the settings and it seems like I can actually change the um relation to the category of the user so what I can do is just delete this so I'll just remove I'll create a new field relation atory i s The Collection I'll SEL the categories collection and I would save changes confirm and all was successful now I can try and create in Course once more can come back to the application and I click on continue and as you can see we have this order error saying only admins can perform this action and that's because by default in Pocket base only admin can perform certain actions so go back to our dashboard go to the courses first of all let's attend to the categories click on this settings go to API rules what I'll do is unlock and set custom rules so I'll just click on here you know in fact we can set admin only because we want only admin to be able to create collections leave this here for the view rules it says admin only but I want to unlock and set custom rules so if I click here I can set custom rules and I can also leave empty to Grant access to everyone which I want to do the create rule I want to leave this for admin only the update rule I want to leave this for admin only delete and I also made a mistake at the first field here I said that on this for admin only but no I want to unlock and make this one visible to everybody because this is the list rule that means get all the collections so I want this everybody's be to view the collection so I'll leave this here now I'll save changes and I'll come to the courses go to the settings and API rules what I will do here is just click on this button here I'll click on this button here as well and then the create rule I'll click on this button but this time I'll add some rules I'll say add request do. ID if is equals to if it's not equals to an empty string and make this double quotations very important to and I'll copy this and I'll just paste this over here for the update rule for the delete rule as well and I'll save this changes so what we are seeing is only a user that is authenticated should be able to perform any of these actions so I'll save the changes and now let's try this one more time go back to our application and click continue and we should be redirected to that C slash the ID and now we have in this page c not found and that tells us that it was successful you can go back and we can actually create this page so I go to my Explorer go to the courses route and I'll create a dynamic page or a dynamic route so I'll just come say create route and in order for us to create a dynamic route we have to put it in our square bracket that will say course ID now what I name it enter the plus page the plus PS click enter and those should be created for us and as you can see as regular I misspelled C I'll just rename this s e and now room the code I don't need which is first of all this and no we need need that I don't need this this and I also don't need this one at the top and we'll go to the server file remove this part we don't need this part move the import as well and in this load function I'll just D structure couple of things from here I'll get pars comma and I'll see Lo house and lo house I'll the structure user and in the load function I'll say cost ID that will be the structured form harams and I'll say const user ID is going to be equals to user do ID and since this could be undefined I'll just my question mark here and I'll say if user ID does not exist so I put commiss Mark in front of it I'll just redirect them back to the own page and I'll save this and we have a little mistake here in the redirect the first argument is going to be the status code so 303 save that once more and if I shck in the browser now you see that we don't have that not found error anymore and let me dis divide my screen so we can actually see the changes reflect as we could what I want to do is actually get this course so now I have created our course IED to this page I to actually get this course itself so what I'll do is create a function here called get course so say missing function course that's now to spell function say get course and I'll pop my try and catch block here I say try catch and in the tri block I want to guess this course so before I'll do that I'll need PB for pocket base I'll D structure PB from look house and back in my tri block I can see const cost let me just give this a line break con cost will be equals to await PB do collection the collection we are targeting is the the CES collection now say dot get one this is to get one um record and in here I'll put in in my coures type but we've not created that yet so let's ignore that for now and I'll say course ID I'll save that what I want to do is because of we're using typescript I want to add a generic here so I'll go to my um my components file not not in my components actually my le folder I'll create a file called types. TS and in this file we I'll put all the types that we need so here I want to create our cost type so I'll say export type cost would be equals to record model and that record model is going to be from pocket base then we extend this by using and C schema and we have we haven't actually created course schema course schema is going to be a type from the C schema itself so I'll show what I mean so I go to the schema. Cs and in here we have this C schema but this C schema is actually a Zord object and we can get the typescript typing typ in from this we can just say export type capital letter so say cost schema will be equals to Z do infer so want to infer the type I say type of cost schema now we can get this score schema from the type so we extend the record model which is from we also want to get this C schema we import this from where we just orted it from and we not done extending open our qu braises here we say user this is going to be string and after that we'll say expand and I'll explain later what this expand means but just follow along for now and we'll put in here craes let's say category category is going to be a type category so we can just come under here and say const export type I mean category which be equals to record model then we extend with and open our qu brazes and the field that we have there is name which should be of type string then go back up to that expand that we add I want to type in some more FS second one here is going to be user and for user user is going to be the type of alt model and ALT model is going to be from pocket base as well want to continue expanding some more things so I come under there and I'll say I'll open like a string and I'll say attachment open my bracket and see course this might seem confusing now but what we are doing here is because of we are going to be using backward relations in Pocket Bas now for the type to work correctly this is what we are using but if you don't understand what's happening now don't bother just write as I'm coding I'll explain to you in due time so I'll put my question mark in front of that because of this could be either undefined so I would say it should be a type of attachment and to be an array of attachment now let's create the type of attachment under here I'll say export type attachment would be equals to record model and qura is open say name name would be of type string say url url will be type file you say cost and cost B type string and here we also have expand as well and expand want to expand cost and cost be of type course I already have type course here and let's make this Capital letterer anytime we use types I like to make them capital letter for me to differentiate them from other things so after the course we can just save this and we can go back up here and keep creating more types in the expand after I've done the attachment we want to do more backward relations I'll say chapters and any chapters will open our bracket here and say cost and this one would be a type of shapter and put our AR brackets there we come under that and we also say pese and that's now how to spell pese p r c h SE and see and this in here is going to be a type of purchase still didn't spell purchase correctly God save me and what we can do here is Define all those types there so the first one I to Define here will be the chapters so what I can do is just copy this one here say it below here change the name to chapter and I would remove all of this here I'll start with the title the title will be string and we say description and description will be type string and we say position I'm running BL little by little description should type string not whatever I wrote there and I'll say position position B of type number I'll say video URL and this will be of type string is for would be of type Boolean is free to be of typ bullion as well and cost would be all type string MST now we want to expand here so I'll say x expand and I do backward relations here so I open my string and I'll say marks data open the bracket and in here I'll say shapter ID question mark column and this will be type Mo dat so me that capital letter since going to be type MOX data and make that an array of Mo data now below that want to create the type of Mo data and of pchas so I'll copy this like I said before I'll paste this down here change the name to Mo data and I'll remove all of this here so I'll start with asset ID asset ID will be of type string then we go for the playback ID and this a b of type string as well and the shapter ID this should be of Boolean and below that want to add just one more which is going to be the pches P that here I'll say r h s c PES user be type string and cost bu type string as well just save that all of those that was a lot but yeah let's get rid of this whatever this is now I can move back to that server file I I'm popping just in here the cost type make sure I import that enter and the reason why I'm getting this red line here because of I did not spell this correctly again RS cos ID and I want to add um I want to expand this so I'll just comma the qual Braes and then in here I'll say expand what I want to expand from this is I'll open my string and I'll say the category because the category is a Rel in the course I to expand the attachment the attachment is not a direct relation it's going to be back a backward relation so I'll say attachments parenthesis and say cost next I will say the chapters the chapters is the same thing backward relations the Chapters open my parentheses and I'll say cost and I'll save this I want to explain what's going on with this expand before we move on bucket base uses a SQL light database and a sqlite database is a relational database meaning we can create relations using foreign keys so by having the categories relation in our our course record you can get a link to a certain category through the ID or the primary key if I create a new course and I added to the relation field the idea of this category I mean if I added the category field this category field here if I added to read the ID of let's say computer science which was this ID here this one here I now have a relationship between that this course this my first course and this um category so I can actually get the data that is in that category from this cost because I have a relationship they have a relationship at that point so going back to the way pocket base works and the way it works with relationships this is a direct relation so as you can see the C has a direct relation with the category because I can add the category primary key or the category ID to a course and when I'm getting the cost that certain cost and I want to also get that category not just the ID but the value of that category I can use this expand so this expand is something specific to pocket base so I can just put here in this string I category and now when I get this certain cost of this ID I would expand the category and as we also see we have so these types of expansions they called backward expansions or backward relations and this one works in a different way as to the relation is not directly in this course the relation is in this um attachment and chapters collection and now when I check my pocket based admin again you see we have actually not created those collections so when we create those collections I'll explain how they would work but when we create those collections like the attachments collection the chapters collection we would add the course ID directly to those collections or to the certain records that need the relations to those Collections and from here we can we can expand it using backward expansion so it's just a very cool thing that pocket base allows us to do Park expansion and we can expand those to not just get the category that is a direct ation but to get the attachments and the chapters as well if you didn't understand it fully don't worry as we move on you will so let's continue so out outside of this Con I'll just put here if course do image URL and as you can see because of we've added typing to this we get all of the expected types now I'm checking if there's an image URL if there is I want to do something very nice I'll would say const image URL that's not to spell image URL so b equals to PB dot fils dot get URL and reason why I running this gu URL method gu URL is because of when we save these things to pocket base the only thing we get is not actually the file itself but a sort of ID of the file so to get a full URL of the file we need to get use this get URL method the get URL method expects two arguments the first of which would be the record itself and the second would be the found name so we'll just pop in here the first is record which should be this cost that we've gotten and the second would be the F name which should be cost do image URL then we now replace the former image URL with this new image URL because this new image URL has the absolute URL so I will now say C do image URL would be equals to image URL and after this if block I will just return the cost and the cach block is going to be very similar to The Way We ring our cach blocks to e and then in the block itself I'll say cons status is equals to e as client response error you just have to import this from pocket base and I'll say if the status was equals to 404 meaning not found I'll just showw error and error will be from spell kit we import that from spell SL KET and the first um argument will be the stus codes I'll say 404 and I'll say C does not exist and outside the try and catch you know what inside this catch after we we've done this we can actually do something else so we can actually just throw this aror page of C does not exist or we can redirect them so we can redirect them back to the own page if a cost does not exist so it's it's your choice whichever one you want to go with I'll say 303 command to the own page now I just comment this redirect because of I don't want to use the redirect I want to show them this error page but if you don't want to show them the error page you can redirect them to the own page after we are done reacting this get cost function we write another function to get the categories I'll just write in sync function get categories and it's going to follow the same pattern without have a try and catch block and in the tri block I'll just write WR down category will be equals to our weight PB dot collection we are targeting the a g collection and here will say get full list and the reason why we using get full is because we want to get every single category in the first one we used for the C we Ed get one because we just want to get a single cost and as an argument we pass the cost ID that we want to get and the get full list we don't need to pass anything as an argument because we're just getting the whole cost so I'll say get cost I mean I'll say get full list and here I can put my generic or my type and the type I'm going for is the category type so remember I created that type I just a category here and I should import this from the categories type or the type file exactly and I click on enter and that should be imported by Visual Studio code and in this brackets I'll just put in my craes because of I want to add some options and the options I want to add is a sort option now I want this to set to sort in descend descending order so way I'll do is just say minus cre created and I want to sort with the created the created field in descending order that's basically what this is telling pocket Bas to do and after here I'll just return the categories and in the cat Block it's going to be very similar as well so I can just copy this part this status part and then here we'll checking for the status code and if it's 44 we not be showing this error we just be dirting them because of if we did not get any categories then we don't want to show them that page so I'll just say um if the is equal to 44 I'll just redirect them directly 303 to on page what we can do next is just come to this return block and in this return block we can just say um cost would be a weight get cost and then run this and we can do the same for the category as well you can see atories would be how it get categories but what this would cause is going to be water falls so now we're going to be fetching the cses for and only then when we fetch the courses we then fetch the categories this could lead to a bit more loading time and we don't want that want our app to be as performant as possible so the way we do this we use parallel it's a fetching method so the way that would work we just say const inside our bracket will pop out the cost and after the cost be theories equals to our wait because once load this in parallel we have to use promise. all and we'll put in this our parentheses an array of values the first one will be the get cost function you have to be a synchronous functions so I'll say get cost call that and the second one is going to be the categories so I'll say get categories and I'll call that as well now this will be run in parallel and I can just pop in here directly the C an category so I don't need this a block here as well and this should work just fine like this now if I save this I'll would go to my page file itself and in here you see we have this less data and this L data is going to be strongly typed so the typing will actually reflect so I can just say yeah data dots course Dot and as you can see we have all the types I can go for typle I'll save this and this should reflect in my browser as you can see we have my first course which is the en tile of this setting C that we are fetching and I can also get the categories I can say in a each block let say each data dot C Gories as category and then like a P tag that just going to cover cover them let's see gory dot name we having this error okay it seems to have disappeared but it's back telling as the argument of type category or undefined ising to parameter of type I really like on known and that because we have the undefined there telling us that type undefined is not accable to an each block but it's not going to be of type undefine so that would disappear in a minute and now as you can see we have all of the CATE is been listed here we have computer science we have music we have Fitness photography accounting engineering and flaming can get rid of all of these and now that we know that it's actually working we can get back to actually building the application first thing I want to do here is the structure of the courses where I say is dollar sign column C would be equals to data dot cost not data transfer data do common data dot cost and I have the cleaned up the data the export let data so I'll just put that back export let data and now from here I can guess the required field so I'll just say dollar sign colum required fuds would be equals to an array of all the required fields that I need so the first required field would be C do title that is a title the next one would be cost dot description and the reason why we keep getting this question mark before the dot is because C title C description could possibly be undefined with the way we set up our data fing now if you check this you'll see that I go back to my Ser file I will see that my get cost could either be my get cost sorry could either be a promise or on the find so it could either be a promise of cses or with this sign here undefined and we also have the same problem for categories as well it could either be category or undefined so in order to actually avoid this thing it's not actually an issue but because of I'm very sure that they would have a cost and they would have a category and if there is no cost and there's no category I don't want to show them this error page because having this error page is not giving way for this to be a possibility that it could probably not exist and I don't want that so I just remove remove this I would comment this and I uncomment this redirect so redirect is going to be what would happen if there is an error and I also comment this as well and just leave the redirect here as well because of the get categories could also be undefined I don't want that so I remove this and now my get categories is just going to get me the categories and my get cost will just get me the cost no undefined possibility there now we can get rid of this question marks and you can continue the next requir field that we need would be the cost image URL then we'll go for the cost price and the category as well and now we want to use the expansion so if you want to expand it we say cost dot X and question mark dots in and now you see we have all of this because we actually added the types to them so I can say how to expand the chapters here like this as you can see it comes in this brackets then I'll say question mark dot sum and here I would choose look for shapter so when I done this I'll explain what we are doing shapter dots is published yeah now what we are doing here is first of all we have an array of required fields and the required fields are the title the description the image AR the price the category and at least one chapter must be published so a course can have multiple chapters so what we are checking for here is in the arrays of chapters we want at least one chapter to be published that why we using the sum but if we wanted every chapter to be published before able to publish the course we use every so that's the difference between some and every so after we've typed out the required fields that we needed I'll just type out the total Fields as well so I say colum dollar sign Colum total Fields is equals to the required Fields do length simple and now I'll Sho I'll look for the completed Fields so I'll say completed fields and a very easy way to get all the completed Fields is by saying required Fields do future and then I'll say Boolean then I just want to get the length of all of them length so what I'm saying here is I'm looking for the required fields that are of try value so if they of try values it means that they're not empty simply that they have passed the test and then I want to get the length of all of those required fields that pass the test as the completed fields now outside the script tag you know what but actually done so go back inside the script tag and now I want to create a completed text so I'll would say text will be equals to I just put my back tick and I open my brackets and my brackets I will put in the completed fuse so that'll be the number of completed fs and outside that I put slash and I open my dollar sign and C again and here I'll put in my total FS like this I want to get rid of all the spaces after this slash because it looks better as this and that will be the completed fi and I also want to get a boan Val of each complete I'll just say is complete would be equals to the required Fields dot every and then just that same method that we used last time I say buling now what this complet is doing is checking if every required field returns a true to Value if it does then this will be yes if not it complet to be false now outside the script tag I have a if block and let me divide my screen so you can actually see what's happening I have an if block and in this if block I just want to check if the C has been published so I'll use my exclamation mark and I'll say C dot is published so I'm checking it the C has not been published actually and if the course has not been published I want to put a banner or a little alert at the top I'm using the alert from Chen felt and as I have previously said over and over I have installed all of the components that I need for this application because of at the beginning of building this application I was having some issues with ch and felt now it seems to have been resolved but what you are going to do now is go to Chan fi documentation go to the allert page click on the C to add The All Out components to your application and just run that in a terminal since I have done it already I don't need to run it again in thisal so what I just do here is type out the aler code snippet and since I'm using the chn felt vs code extension I can just do cnx and cnx would pop out this and I'll say out I'll say a ler I mean and we have all of this code and we also need to import this as well so I come above everything and I say cni a lot and it's will import that for me and in this Roots I want to get this a class so I say BG yellow 200 little bit of opacity so I say over 80 and I get this a border and I want to make that border yellow of 300 and I don't want this to be rounded I say rounded none now once I save that we get this as you can see we have this allting head up you can add component to your app using the CLI and that is L the text that we have in the title and the description now I want to put an icon after this so I'll just come here above the AL TI to I'll say aler triangle and this should be from Lu F so B decided that it will not assist us with the importation so we'll do it ourself I'll just give this a class of size four and I'll go above here to my inputs and I'll write import open qu braises allert [Music] triangle [Music] from Lucid spell and once I save that the triangle icon should pop up and as you can see for yourself we have the icon there now for the title we would leave it as it is but for the description we would change text that we have there so in the description I'll just type this course is on published and let's now use JavaScript to be type in here I'll say unpublished just like this it will not be visible to students and I'll just save this and after that if block I will have a div and in that div I'll give this div first of all a class of P6 so paring all round of six and not 64 six so in that div I have another div this div would have class Flex item Center justify between and inside that div again I have an H1 that says cost set up so let me save that and see how that looks now we have this C setup I want this C setup text to be larger so I'll give this X1 class and I just type in text 2 XL font medium now that should be larger and thicker right after the is one I have a span and this span will have a class attributes and say text xsm testt muted foreground and in the span I will say complete all fields and in that complete all Fields I'll put in my completion my completion text or my complete CED text actually so this this one right here so I just copy it and I'll paste it right here and I'll save that and we should have that reflect in our browser here complete all Fields one over six because of we actually have a title at this moment so we have one field actually completed now as you can see we have the course set up and the computer on fi having this little thing of being by their side and that's because of rising Flex so the complete set up is one side and the complete off Fus on on the other side I don't actually want that so I'll just wrap that each one and the Span in One D and when I save that they should come together like that and now I I'll just give this D some classes I'll see I also want to make this a flex container but Flex column and I want give this a gap y of two once I save that that should look a lot better nice now outside of this div the container covering the H1 and span tag I want to add an action so the two actions we be adding is the ability to delete the course and to publish and unpublish the course so before we actually build that action because the action is going to be a component itself I would just have a comment here saying actions like so and this would remind us to add the actions here so we can come out of this W div here but still inside this div of P6 I have another div and this div would have class and this will be a grid container be a grid columns so grid code one that'll be for the mobile screens then on MD this will be grid Co two and GAP 6 Mt 16 and in the div we have another div and inside that div we have another div and this St would have a class of flex item Center Gap X2 and in this D we're going to have two things we're going to have a c badge component so I'll say icon badge now be a d g e and here would have an H2 that would say customize your cost let's H2 have couple of classes as well I just give this a larger text say text Excel when I save this you see it reflect in the browser say customize your cost and what I want in this icon badge is just a little icon at the side of this customize your course two ways you can go about this is actually just creating the icon here of in this place but thing now is I want to reuse this certain type of style that I'll be given to this icon in multiple places so the best way to go about this is actually creating a new component and adding that icon there and then creating it in a way that it will be reusable for multiple use cases and using it in every other scenario that I need to use it so I come to the component folder and in the component folder I'll create another component called icon badge do sp now things might get very funny so I would really like for you to follow me along closely the first thing that I'm going to do here is actually import some things that we need so I'll say import TV and type variant props this will be from Tailwind variance now you don't really have to worry about whether Tailwind variant is installed or not it would be installed if you use the chanf CLI to set up chian but if you didn't then you're going to have to install this manually and after that I want to create an icon variant so this is because of I want to be able to have different types of Icon I want to have a default icon I want to have a success icon I want to have different sizes I want to have like a normal size I want to have like a large size and I want be to add variant and I also want to use this opportunity to show you how to create variants so this is a very similar way that Chan felt goes about creating this component so if I go to the the Buton component of chian felt you'll see that here we have variance this is button variance so if I click on this button variance is basically what we have here we have this I'm not supposed to click on it but we have this button variance here and then here we have this TV so that is the TV that we're importing and that's just a utility that Tailwind variance gives to us for us cre variant so the first thing here is the base so the base sty and then we can add the variants now we have the destructive variant we have the outline variant and those will be the styles for the ACT variance we have the secondary this will be the styles for it we have the ghost this will be the link and this will be the Styles and then this is the default and this will be the Styles we have the for the size as well for the default we have the styles for the small we have the styles for the large we have the style and for the icon we have the Styles and we can now say the variance will be the variant and the size and put the name of the default Vari I want and it's was the default and that's how easy it is to create very reusable component using T variant so going back to our icon batch we'll be following that method of creating um variance so I'll just say con icon variance would be equals to TV if you remember that was how they started TV and then in yeah we have C braces and the first thing will be base and for base we have rounded full Flex items Center and then justy center after the base we can start in the variance so I'll say variance and in here our first variance will be variance and we just say the default again following the way Chi say default and the default does not have to be named def default just so you know what again CU I want to follow Chan f P I'm going to call this default that's a BG Sky 100 and text Sky 700 then we have for Success this will be BG Emerald 100 that's not spam R yeah BG I'm missing an e here always missing one thing mgal and then this will be text Emeral 700 and the second variance will be having will be the size variance say size and we have defaults the default St will be p two H 10 and with 10 so we can do H 10 and withd 10 another thing we can do is just use size directly now so size 10 then we can go for SM here I'm going to say P1 and size would just be six instead of 10 and now outside of the variance and now say default variance would be for the variant variance I say it to be default because of that's following and as for for the size variance it's going to be default as well now outside of this icon variance that we created I'll see type icon variance would be equals to variant props variant props would be from Tailwind variant to be a type of ta variant which we actually um exported or imported sorry at the beginning of the file so I'll just say variant port and I say yeah type off icon variant so what I'm doing here is just creating this type from icon variant directly so I could have either add coded this or I can just let variant props infer the type for me just like we did for Zod as well so now this will have the type like if I over this you can see we have the typescript typing for the variance and size now see here type props will be equals to to the icon variant type and icon will be component type which should be from SP and you will be icon and icon will be from Lucid felt because going to felt icons that we be using and after that you can see type doar sign doar sign props would be equals to the prop that we just defined and it seems like component type was not actually imported so let's try import this again now after that we can say export let variant is it type dollar sign dollar sign props open your square brackets variant and be equals to default I'll do the same for the size as well so I'll say xort size this here will be size and to be default and we'll do the same for the icon but for the icon we won't add the default so say ESL icon for the prop we say icon so in this in this div tag we just have a sp component I'll say s column component and to be a self closing tag and this would be from icon that we are defining as a prop here and in the class we just use CN so open our C Braes on CN and we're going to have to UT CN remember CN is that utility function that we defined in our utilities file or that Chan felt defined or created for us now in this I'll just say first of all icon variance and in icon variance my C and puts the variant and the size just like that we created a completely reusable icon badge component so I'll make sure I save every file by doing control k s and then I would divide my screen so we can actually see the screen and now use this component now going back to the page I can now come to this icon badge um comment and I'll remove this and I'll import the actual icon badge component okay so if we just look it again does no want to help us to import this so we'll import this ourself and I'll say above here import icon bad from dollar sign leave slash components slash icon badge do spel and once I save that you should see this pop in our browser beside the customize your course text and if I go back to the icon badge you see this red line because of we expecting the icon prop but it's missing so we just say icon is equals to call braises and here we pop in the icon that we want to use so the icon this time around would be the layout dashboard and Rd and I'll just import this from Lucid felt so I can put it beside this aler triangle and there once I save this you see the icon pop inside that Circle and here I can actually use those variants I added so I can see size and by default the size give us the default that we set so if I go back to the icon BGE if you don't add this size property we get the default but if you want to use something else we can just add it and use the other ones we want to use so for example now I want to use SM can come here and I'll just write SM and the good thing is here we get Auto completion so when I SM I save that you'll see the icon get smaller and if I remove this you just use the default styles for me so this is a very nice way of creating reusable components that's why I decided to show you and when we've created this div just just outside of it I want to add a couple of components here I would add the title form component I would add the description form I would add the image form and I'll add the category form but I don't want to begin creating those components but until I have created this whole file so what I'll be doing is just using comment to identify the places that I need to add this components so first of all the first component will have here will be the title form component so I just write title form the second component we have here will be the description form components here and you'll have the image form components here as well and also have the category form component as well now outside this div that will be covering this icon div and the components as well we create another div and that div would have a class of space y six so I just say class space Y6 and inside that div would have another div and inside that div would have another div and this div would be a flex container so we just get a class of flex items Center and Gap x 2 now in this div we have something very similar to one we have here so we can just copy this W in here and paste it right inside here and we have to change some things the first of all we need to change the icon so I've changed the icon from the layout dashboard to the list checks icon sorry checks and I'll just import this from Luis fi by adding it into this qual brazes like so now change the text as well instead of having customize your courses I write course chapters course chapters like this and I'll save that and don't to make this capital letter here so the C could be small letter I feel like it looks better that way and that's not to spell shter anymore so outside of the div that is covering the icon badge and the cost shapter like can you believe how I spell course forgot the O all right so outside of the div as I said I want to create another component so I'll just use comments to signify that I need to put the components there I'll just say the sharter form component would be here we'll create that later now outside this div covering the div that is covering the icon badge and also the chapter form component I will come out of that and I create another div now mean this div would have another div and this div would have a class of flex item sent and GAP x 2 very similar to the way we are doing this and if you know the drill now we could we could just copy this so we don't have to rewrite it again paste it here and just change the icon and the text so the icon we be using this time would be the CLE dollar sign icon okay sign and I'll just copy this and I'll import this from Lucid felt and I'll change the text from cost chapters to sell your cost and I can just copy this W div since we're already getting the w wrew I'll copy this W div but before I actually paste this here outside of this div would have another component here so signify this with comments and I'll say price form and you come out of that D and paste this one right here and we'll just change this time we'll change the icon so from C dollar sign to fou and we can just copy file and paste it directly in this craes here so it will be imported from Lucid felt so we can also change the text from sell your C to Resource and attachments or resources and attachments instead of using and we could just use this sign it's better and this is supposed to be C and not s so save this and this should change from C chapters to resources and attachments and outside this div for the resources and attachment we have another component here and this component is going to be the attachment form so I'll just say attachment form now that we done with that let's just look at how the structure is right now you can see that this thing is in two columns and that's because of at the beginning we identify the parent or the container as a grid container so right here it's a grid container and from The Medium screens to the larger screens it's going to be two colum grid but on the smaller screen is going to be a one column grid so if I increase my screen WID or my screen size sorry you see that it becomes one column and it stacks on top of each other and the reason for this is so that it can be respons responsive sorry responsive on mobile screens so now let's move on by creating each of these components starting from the title form component now open your Explorer and go to your components folder and in your components folder create a new component called title form do felt remember to make it a felt component it has to have the extension that's felt and I'll just do sfc to get the script and a div which is a little emit I created by myself and we can begin so and a container div and a class attributes would give give this a class of six um margin top six sorry let's give this a border yeah get this BG muted rounded MD let's go with MD and P4 we'll save this and go back to our plus P felt and we remove this title form here and replace it with the the title form component and we can just import this from where we created it just make sure it's imported let's take a quick look and yeah title form right here save this and go back to the title form component now we can see it while we build it in this here and in this div we have another div this D have class say font medium let's go medium flex item Center justify between and in this div would have the title which is cost title save this and we should have that nice now still in the that div you want to add like a button to like an edit button where we click in and it tles the edit state so or the edit UI so we say button I can use my CN x button and I would come to the script tag and say cni button and in this button I would have an on click so on column click and you right here would have a toggle edit function that would create right here so let's come up and create a toggle edit function first of all we say let is editing is equals to false and say function toggle edit would be just strling is editing to the what what it Opposite was so I say this editing like so so now if is editing was false it will become true if it was true it will become false now go back to this button we want to give this a type so I'll say type of button and a variant of ghosts now in this buffing we have an if block so I'll say if it's editing I say cancel sorry I spell cancel wrongly everything single time cancel and else and I want to show the is editing or edit title text I'll say edit title and I also want to have like a little icon so I'll just put the pencil icon to indicate that it's editable so see pencil and pencil will be from lucis felt so I can just click here and I will give this a um let's give this a size of four that'll be a width of four and a height of four say size four and margin right two save this and we having an error saying that and let's read what the eror is saying saying ATT to close an element that's was not open and let's take a look at this to see where the error is coming from as you can see the if block is open but it's not closed so we need to close this if block come here now say if save and this error should disappear now now we have this edit title button and when you click on it you get to cancel when click on cancel with toggle and get to edit title that's the functionality that I want now let's move beyond that outside this D that is covering the button and the C tile would have another if block so we say if is editing is true so that is exclamation mark is editing because remember initially is editing would always be false so if his editing is true then sorry sorry if his editing is false so meaning that if we have his editing to be false that is this state it is in currently that was a silly mistake that I made this just says is is edting is false no matter what I declared is exiting is initially whether it's true or false it says if is editing is false now if his Ed is false what we want to do here is just have this this B tag and this B tag would have the ti two so you can see this that's right this is the title we replace that with what we need and we get rid of this qu bases because of we think this is supposed to be JavaScript but we'll replace that in due time and this P tag would have text SM margin top of two save that and this is how the title will have it this is the title to and now we have our else so we say else that means his editing is true now we have our phone and this action is going to be slash teacher slash courses slash the course ID so I'll just say ID here for now then slash question mark slash and the named action will be targeting will be update Title so say update Title and after the action we have a method and the method will be post uppercase post and will gives class of space y 4 and margin top 4 and since we're using a form remember we using spell kit super forms to handle all our forms so we come into our script tag and just above all of these but below the import I would say let's say export let data and this export let data is not the same export Le data that we use when using a plus page that's spell for this is just a property or a prop which we can name anything but I'm just deciding to name it data so I say exper l data would be just like so and then I'll say const form is equals to Super form and that's going to be from spell k super form and in here the first thing will be the data and second thing you will be the options and in the option we can have our validator which we can pop in our Zord schema so let's create the Zord schema for this so I'll go here I'll go to our schema file and if you remember we have result schema already created this title schema right here so I can just go back and say title schema and just make sure that Imports correctly good and we're having this um issue here it's saying that we can't directly put in this title schemer we need to put in the adapter if you remember we've been using that pattern so I say Zord client because we using a Zod validation and that error should go away and we'll put comma right here don't put it like that seems like the result client did not import okay now in order to make this data strongly type and just come here say column to be of type super validated then we use the infer and the infer is going to be from SP K super forms yeah and in that infer we can put in our title schema and this title schema is going to be a type from the title schema itself so we need to create this so I'll come above this and I'll say type title schema would be equals to type of and then pop in our title schema here and now any error that we should have ADD would disappear just like that after doing this I can D structure from form some couple of things that I need like enance and form data and delayed submitting and so on and so forth so I'll say equals to form and from here I'll get i'll get form as well remember form and form we can have to the same name so I have rename this to form data yeah I'll get an an I'll get delayed I'll get sub meting now I can go back to our form component just make break this into multiple lines and you see the place that we put this ID what I can do is remove the is open my Call braces and I'll use the page store itself to get the params that we need I just use dollar sign page and Page will be imported from App SL store so I just come above everything here say import page from sign up slash stores and I can use the page store and the page is a store and that's the reason why we have the last front of it see page dot params dot c not this course ID and I'll save that and no error should occur okay error did occur but let's just keep on going so we have the this new format sent to Super form make sure blah blah blah and that because of we actually aren't sending any format yet but let's continue after this method we can have an action for enhance so say use enhance like so now in this form field we start adding our FS that we need and I don't want to rewrite this W thing so I can go to my login page I have written this already and I'll just copy that field part and I reuse it I'll paste it right there for the schema part is going to be wrong so what I need here is the title schema or the title field sorry I'm using need to import form itself so I'll come above here and my cni doesn't work for form I just remembered all write this import aeric as form from sign leave slash components slash UI SL form save and now we need to import the input as well my cni work on the input probably so I say cni input like that and now we having this error because email does not exist on the schema the only thing that exist on the schema is title correct and I'll change the label as well from to title this time I would also add a placeholder on my input yeah I would say just give an example adance web development after the FI still inside the form tag I have a div and this div would have class Flex item Center Gap X two and inside this D we have the form button I'll write form dot button and I have my if block cuz want to check for delay so we can add the loading spinner I'll say if like this I'll say dollar sign delete loader two and this is going to be from I always make that mistake is going to be from Los fault and the class would add here would be size six animate spin terrible spelling size for God's sake then we have else and if theay is false we just say save and we'll save this W file and we go back to our page so our plus page not this one the one for the course ID yeah now we need to add to this data props the form that is been returned from the server for this title form component as you can see by over the data the type that we expecting sorry the type for this data that we expecting is um it's not working now but it's this type that we added here this super validate in the title schema it's going to be this title forms form that we returning from the server so let's do that now let's go to our server file our plus. server. CS So Below this promise. all that we got here I write const title form will be equals to await super validate and the first argument for validate will be cost and the reason why this time the um first argument is this cost that we're returning from the that we are getting from pocket Bas because of I want this to give me the title form default value so since we've added the title form before I want that when I load the page I'll be able to see the default value of title form or the initial value or previous value of title form so I can actually do course dot tile here but because we're using SP ke super forms it knows which one to add here all it needs to do is just the Json that we are returning or we adding to this validat should just partially match the schema that's all it needs and it would know what to add so the schema that is going to be is going to be be Zord is z adapter remember so we just need to import that and inside the Z adapters parentheses we say tile schema like that and in this return we can return the title form as well and going back to our plus rious f file in this data we can write data. tile title form if you remember that actually what we are returning let say title form now we having this internal error let's just save everything and see the way it looks like when we saved the plus page f file and the plus page have CS file as well now we are still getting an error and that should be in this on the server because of it's an error of 500 so let's check the server F well and you see that super validate is not actually being imported just make sure you actually import super validat from Super from spell k super forms sorry so we go back to the P just f file save every file and see the way it looks now now the error persists and this time we having this error here saying that type super validate any is not ascendable to Super validate s to so since it's 500 it's probably from the server so go back to the server file and title schema is actually not being imported as well so import tile schema let's see this file first of all make sure that we check that everything is been imported categories just title K is actually not still being imported now to write this by hand past right there right here title schema and now I'll save this file and the error should go away in a second and as you can see the error is this appeared and just make it full screen when I click on this edit title button you see that we have this form and I I click on cancel it disappears and I can actually edit the title but if I click on Save nothing happen because we don't have the form actions yet so let's do that next so in the server file we just have our actions so I can use my little Emit and say kit actions I'll get rid of the part that I don't need I remember the name of this action so the name we gave to it was if I remember update Title so that's name I'm going to use under here I'll write update Title and in synchronous function synchronous Arrow function actually and here get event and from invent I'll D structure local and from local I'll D structure pocket base PB I see consal to event and from here I'll get locals and from locals I'll get PB and I also get params from here as well so I say params and to get a course ID I'll just structure it from param say course ID is equals to THS under that I'll write con form is equals to A wait super valid dat first argument would be event second would be the schema so I just write Zord and I'll put the tit to schema under that I will share for the form validity or the form valid status I'll say if exclamation form do valid return fail and fail will be from f/ kit if St code be 400 and in this call bases return the form remember you always have to return the form except you are redirecting see my TR C block would come in here just like so I'll turn this error to just e and in the try block I'll write our with PB do collection collection we targeting now is the CES collection and we want to just update the title I say dot update and the cost I want to update to just Po in the ID so say cost ID and we say form do data and form. data just um contains the title so it's just the title that would be edited or updated and I'll say re return message and message will be from SP kit super forms and the first argument will be the form the second will be the message text I'll say I'll just write successfully updated C I2 or something like that I think that's nice and in the cat block very similar to the one we have on login page so I'll just go here and I'll copy this rewriting this this is not where we want to be we want to be here and in this catch block I'll paste that I need to import client response error and for the error message we won't do this format we get rid of this here in fact we get the error message directly from pocket base so say message and because of message and message are the same name don't want the same name you're not allowed the same name so I say error rename this error message so after message I mean after we've added the form as a false argument in the message we now the second argument will be error message and the third one will be an option so just say status and the status that will be using will be for Android for this case let's make sure that this message function is been imported yeah it is and now I can save this for and I can try to update this title and see how it goes back to our browser let's check out how this would go so let's try and actually update the C title So currently we have this is a title as the title which is not what we want so we want the title that is being gotten from pocket based back end or from our server whatever so I'll go to that title form component and in this place that we have um this is the title I just remove this my CRA is there and I write data dot data. title and the best part about all this is that it is strongly typed now saving this we should have right here the title that we initially used to create this course which is my first course and clicking on the edit button editing this title should edit this title basically so say my first course and I'll just say edited and I click on Save and it saves it but you see that I still have this my first course showing but when we remove this we have my first course edited right now but when we go back to our edit we have my first course and this shouldn't be so so I'll teach you or I'll show you how to fix this issue so one way of fixing this because of I don't the only time this would actually update is when I refresh the browser so if I refresh the browser now that the browser has been refreshed you see that now it shows my first course edited I don't like that format I want is that when I change this title it reflects here instantly once it saves one way of doing it would be changing the reset form options to false and in the past for St SK platforms it usually was that but now it has been changed so we can just easily come here and say reset form and say false save that and now when we edit this you should see it change so say edit two so we can just say edit and then put two therey that this is the second time we editing and when I save that you see that it doesn't change back so my first course edit remains at two and when I cancel this it shows my first course edit two and if I come I can write edit three and save that it shows my course my first course edit three and if I can see here it shows my first course edit three as well that's what I like and the other thing that I don't like about this experien is right now when I click on edit title when I edit the title once I click on this save and it was successfully edited I want to have a notification telling me that this course was successfully edited and I want to be moved from this States so his editing should move to Force so I can just see this my first course edited whatever title that was so the way we use the way we do that is by using the unupdated method so under this reset we use unupdated and it's a meod so put it like this and in here we can the structure form and in the block or in the CRA I can have an if statement I'll say form do message so I'm searching if there is a message being returned and if there is I also want to check if the form is actually valid I say form do valid and I would put my exclamation mark in front of that and if the form was valid I'll just open a toast notification here I say toast dot error I mean if the form was invalid I don't know I keep making this Sil mistakes and this is not how to spell message for God's sake I'm getting tired of my own bad spellings at this point so I'll say to the error and in here I'll just put form Dot message that is the message being returned and remember we don't have toast being imported so we need to import toast so I just import to from spel sooner and if it was actually valid I'll come down here and I'll say if form dot valid I just Lally just written El but I have to write another a block anyways it work the same so I'll now check if the form is actually valid I'll now say toast dot success form Dot message and in here if it's successful I want to toggle the is editing States just like the I said earlier I just put my toggle edit function here and I'll save this W thing and now let's test this out one more time so click on edit title button and I'll just say this title has been eded and I'll click on Save and once I save we have this to notification telling me that success updated course title and the C title has been changed to this title has been edited and that is exactly what we wanted now that we are done with the title components let's move on to the next component and the next component would be the description form component so let's create that our component folder description form do spelt SSC there and I right here this is the description component and in here I'll remove this description from comment and I'll replace it with the component itself description form and I would import that like so make sure that I actually imported description form now let's go back and let's start building this component now this component is going to be similar to the tiple component but with some little differences so let's begin with this container div and in here would have a class and the classes that it would have would be mt6 a b a BG muted rounded MD P4 and in this D we have another div this D would have class see font medium flex item Center justify between and in this D would have CA description we can make this D smaller T looks better like that and in this after C description we have a button and the button is going to be the button component from Chan felt so we'll just import that I could use cni button to import the button component and in this button would have an if block or a if block It's actually an if because of if starts with I and I is a v okay in the button the if block going to go like so if is editing so we're going to have to create that variable let is editing is equals to force and let's create a function to actually tole his editing like the way we did the last time function tole edit and yeah I'll say is editing is equals to it Opposite is editing and now going back to the if Block in the button component I can see if is editing I want to have the cancel text else I have a pencil icon and do this class size 4 imine right two and then the text of edit description just make sure that we actually import this pencil icon now I'm going to divide my screen so we can see the browser once I save this you should see the changes reflect in the browser so I'll just save every other file as well so I'll typ control KS and now we have this edit description component being built but I don't like this where this button is I want this to be a variance of ghosts save that and that should change now let's move on outside of the div covering the button would have another if block see if is what am I typing is editing is false so if is editing is false I have a p t and this B tag would have either the description or if the description does not ex it we have a default text of no description so the way I'll do this is just something like this I'll write no description yeah but I will have a comment so we can be reminded to add that I'll say add inal or theault is scrip sh I leave this like this and in this B tag I would have a class and this class would have text SM margin top two and break all make this end cap later looks better that way save that and we should see new description there so and we have an else else and here is where we put the form so I will just put my form here my form tag and then we can start building the form with s Kate super forms and form snaps the first thing here is to add the action so the action will be slash teacher slash courses slash the course ID which you can get from the page store directly so I say page and I import this page from App SL stores but remember this page is a store itself so I'll put do sign in front of that and I'll say dot pars Dot course ID and after that the closing craes I'll put a slash question mark slash and then the name of the action which would be update description that's not how to spell description sorry d s and I'll scroll back up and I'll start youing the form with SP kit super forms I will first initialize SP kit super forms let see const form is equals to Super form from s super forms and in here what we want to pass here is the form itself which we are calling data so I'll just come here and say export Le data above here export let data and this will be of type super validated and we use info and INF will be from s kit super forms as well yeah we just open here to pop in the type so it's going to be of type um The Script destion schema so let's create description schema the way we create the description schema was going to be very similar to the way we created the TT schema I just picking it from the C schema so I'll just duplicate this here rename this title schema to this scription again made the same mistake with s and C description schema and for C pick would not pick the title but only the description true all right let's move on so going back to the description but let's check this one more time I think I have an um typle here a spelling error and I missing in description schema spelling okay let's you can go back now and here I can just say type just a type of description scha and we import description schema from our schema file like that and now in these super forms I can just pop in data like that and after the data we have options first options will be our value datas option like so and here will be the Zord client because we are using zeld as our validation library and in here would be the schema which in our case is description schema again the same mistake with SN C schema like that and just something similar to that we did with the title schema or the title forms form sorry I can copy this unupdated because I want to show the Sona component so I'll paste this here and here I'm checking for if do message exist and if the form is invalid I want to show the error the form is valid I want to show success and I want to toggle edit we need to import um toast so I can just come here and let Visual Studio code import F sooner for me now that we've done that we want to D structure from this form a couple of things and it's going to be basically identical to this that we did get in the title form component so I can just copy and paste that as well and moving on down to the form back we can go to the form tag and give this a method of post and say use [Music] enhance it is class space y4 margin top 4 and in here we start popping in the fields this we would only have one field which should be the description field but it's going to be a um very similar again to what we have here so I can just copy this if I copy the button with the loader and everything just copy this W in and paste it inside here and we going to need to import the form component so I'll copy this as well and paste it above here have some other things we're going to need to copy like the loader to Icon so I scroll up and I pop this here after the pencil icon in Lucid felt and we also need the input as well now for the description we won't be using the input but text area so I can just write here text with the capital letter T and this going to be from Chan's felt a r e a so and I would add this yeah and I also add this with the placeholder as well so just the wolfing I'll change the placeholder to this cost is about dot dot dot and the form data will change from title dot to description and we change this as well on the name for title and this as well on label and we'll just delete this input next thing that we're going to want to do here is to actually return data from the server file so I'll go back to the page and see that we expecting one prop data and data will be equals to data do description form we are not yet returning description form so let's do that but spell this correctly go to the server file and actually return description form so here just like the way we are doing for the title form will be for the description form so I'll just duplicate this and I'll call this description form and yeah we not be putting the title schema we be putting the this description schema let's make sure that import correctly yes it does and now we can return description schema after returned title form save this and you go back to the plus page file and see that the error has disappeared I can go back to our descriptions forms components I just control k s to save every unsaved file and I'll see how this is looking in the browser so right now we're having this 500 internal error but the browser is reloading so let's give it a second and now we have the description form component pop up and I'll click on edit description and nothing works so description button isn't actually doing anything and that because of we have not hooked in a action for when we click on the button so let's do that now the action that we are going to be adding for the unclick event is going to be this toggle edit function here so I can just come to the button and say on colum click toggle edit save that and now let's try out the edit description button when I click here I should have this form and when I on cancel I should have the new description once more now what I want for this no description text is for this to be the default text when there is no description but when there's a description I want to show the text what I will do now is come back to where we have this comments saying add initial or the first description and here we just get rid of this comment and we say data dot I remember data is this prop right here so say data dot data dot description or if there is no description then will show this no description text so I'll copy this I P this here for when there is no description so if this results to null or undefined will show this and for The Styling as well I also want to change some things so when the the there is no description I want to make it a little bit um gray and italic so I use CN again so I'll just put my C braces here I pop in C and see would cover this in parenthesis make sure that CN is imported and we could just use the Auto Import like this and now after this and just put our craes there and say text muted forr and this should apply if there is no description nice now let's add the action so that we can actually edit the description first of all we need to remember the name we named this action so update description and go back to the server file so right after the update Title sorry right the update side to can say comma and can say update description and we also put an synchronous Arrow function yeah and in parentheses we can get event and from event we can D structure as usual so we can just say const is equals to event and from event I will get locals and from locals I get PB and I also want to get the C ID so I the structure param from here as well and from params I can D structure C ID now I can check whether the form was valid but first I have to initialize this so I say form is equals to A we super validate I put here in the invent and then I put our Zord adapter and I put our Zord schema description schema I can check if it was invalid and if that was true I just want to return F and this St scode will be 400 and we return the form here and outside of that if block I have my TR cash block and in the try let's say I wait PB as collection I'm targeting the CES collection and here I'll see update and now to update the course ID and and in here I'll put form. data for it to update the data the description because in form. data is basically just only the description so if I use this you see that it's just the description we have so that will update only the description and I can come down here and say message first argument will be the form and the second will be the message itself so I can say successfully updated course description and for the error it will basically be the same as the error we have for the title action so I can just copy the error block and paste it and replace it with this one here now we can check out the description functionality and see whether it would work now going to the edit description button click here and let's type in this is a description for our course now don't mind my terrible spelling you should already be used to it so I'll click on save and here we see successfully updated course description you see this is the description for our course when I click on thisit description button I don't see that text there but that's what I want I want that when I even if this is here when I click on this description button or edit description button I mean I want the text to be here and I can just edit it and like that the only time it's going to come here is when I refresh this and then it would pop there and I don't like that style so remember if you remember the fix that we we did in the sorry if remember the fix we did in the title component for the forms we just added this reset forms to false but instead of having this for every single form that we want this functionality to be there's a different way that I'll go about it to make this basically Global for every single form that we create for this you're going to have to go to your Vite config.js or ts4 and in here just under this plug-in part just write Define and super forms and this must all been op case super forscore legy and then you say true and right now felt kit and V understand what's happening so the best thing to do in this situation is to basically cut your terminal when You' call the Cal you can start it again and I did not spell Legacy correctly so it's Legacy not L Jess and we going to run the terminal one more time can save this file refresh this and the teral should start up at any moment because we're having some funny errors but let's run this one more time and let's refresh the browser go I was basically waiting for the ter to run and then I tap the refresh button immediately I saw this pop up and now it's working and let's test this one more time so I'll come here and I'll say test description now what's going to happen when we save this is that description should change to test description correct and when I click on edit description I you see description as the initial text in the text area field exactly the way I want it so now we done with the course title component we're done with the description components now let's move on and the next component that would be dealing with here would be the image form component so let's build this out this one is actually going to be a very interesting one so let's begin by now you should know the drill move to our component folder create a new component we call it image form an image form be of extension felt sfc and I'll come down here right this is the image form component and I'll go back to the page and I'll replace this comment with that component image form and just make sure that that imported correctly so image form yeah we go back to that from component and if you don't know what I'm doing I'm basically talk limitting to FES so that's is control P to see this and you can just write tap control P again to move do contr PP to talk between two files and here I'll just remember this text because we don't need this now anymore but let's actually visualize that it's actually showing so I'll save all these files just to make sure that this is actually showing the component is actually being shown exactly this is the image form component and I'll come to the class and I'll say mt6 border BG muted because we want that background color and rounded MD this giv um a p of four paral round of four get rid of this this text we don't need this text anymore and in this div we have another div and that div will have class say font medium flex item Center justify between inste div would have course image text after that we'll have the buttton f f just make sure we UT that in our script tag here so I'll say cni button and in this button we have an if block but before we create the if block let's write down some variables that we be needing I'll say let is editing is equals to false I'll say let file input be type file list or null I'll say let uploading equals to false and spell it wrong again and I'll will create my toggle function I say function this toggle edit I get rid of this part and I'll just inverse so see is editing is equals to it Opposite is editing now I'm going back to that button my if my if block right here uh if and I see if is editing know what I'm typing sometimes I put canel I don't want that to pop out when I press enter that's why I'm clicking outside and I'll say else this is going to be else if so I say if else if there is no image URL so this image URL will be a prop just above the input say export that image URL type space type string or undefined now say else if there is no image U and if there is no image that means there no image has been added I'll just put the plus circle from Luis Feld give some class say size four imin right two and in after that plus CLE I just say add I I always say I would just say I'll just say but I'm typing so it's not I would just say it's I will just type I will just type add an image no I would just say I don't know why I keep saying that and after this I was right not all right else and for the else that means this was not um this wasn't true and this wasn't true as well so so it would result to the else when it comes to the else would have the pencil icon pencil and we import pencil from Lucy fa as well put your class are you kidding me I type Z again for God's sake It's s calm down S size like copy I drank this morning is wiring my brain off size let me get this out size Marin right two after that pencil I have edit image like this now we come down after the button and after the div covering the button we have another if block and I'll choose the if block here and it will be if is editing Now to pop in a form and here we put in the action so I can just put in um so if you notice in the description and the title component I've been putting the full URL of the action like now look at the action like SL teacher SLC slash this slash this before I put the the actions name but what I can actually be doing since this component is directly on this page and it's going to be utilizing utilizing the action of this page of This Server page what I can do is just use um relative URL I believe that's what they called and I'll say um does a question mark and Slash and ask here is the action name so I'll say up dat image now you can do the same thing for the description and for the title as well since you just using our component inside this um file but it smart puts the absolute or the full URL so that you can use component anywhere in your application in any page and it will still use this action that is in this file but after doing that that I'll go for my method and in my methods I'll use posts now capital letter P O S and one thing I'll do here is use use enance again as I've been using but this time we won't be using spel kit super forms to handle this form because of for this form we want to send an image and just of lately there felt kit s form start to handle image by the time of I actually building the applicationform I not started handling images but right now they do and you can go to the documentation they have a very nice documentation a very clean um pattern of handling images but but this tutorial we won't be using that would be using plain JavaScript and spel won be using SP kit super forms to and do the images so the enance that will'll be using here is going to be the one from spelt kit self so say in an and it's going to be from App SL forms and just make sure you import this let me scroll up we have this one here andoun from App SL forms and not forms SP forms after that I also want to put in here encrypt type because of we going be sending form data I'll say encrypt type would be this multi pass Slash from data and the class of margin top 4 save that open this form divide our screen so we can see what's going on and as you can see we have this C image component and when I click on this add an image well nothing happens yet when I click on it the idea is that it brings me to the edit or ADD and image form now let's actually add the action for this button and as you probably already guessed this button is simply going to be toggling the um toggle edit or calling the toggle edit so I just say toggle edit here I save that and now when I click on add an image we have it's actually switch the state but we don't have any component there that's why you can't see anything as you can see this whiches the states now in the form I have a div this div will have a class relative and in this div I have an input let's inut be of type file now when I save this I click on add an image you see that we have this shoes file and no file chos on by default and I want to have some classes to this to make this look a lot like the way it looked on the demo so I say class will be equals to first of all want make a we of full and a text of transparence now I save that I C on add an image we have shoes file we don't have that no file shoes in text anymore because we made it transparent now move on after I've done text transfer I'll say height 60 save that and now when I click on this you can see the height has increased you know what I'll do for now I'll make is editing true so that we don't have to always click on the add image button so see true let's just add an A Commentary to remind ourself to switch is editing back to for okay and we can actually have fun without to go back to and through I doing that we say BG transparent as well so we can now start adding cool things like the borders and I'll say border slit 300 and after they added the Border I'll save that and now you see that we have this border around it yeah I'll just make that rounded I just come here and say rounded MD saved that file and now it's a bit rounded if you can notice and the magic to this whole thing is to just say file hidden no file column hidden save that and now that shoes file button should disappear as you can see the shoes file button should disappear but this is still an active um file input so or input file so when I click on this as you see we have this no file Ching something popping up in this area I can actually click and it to pop up my file explorer so that's just a very neat trick there in order to restrict this to just be only able to access images I would say accept equals to image SL aeric and I'll give this a name of image since we handling the form by ourself give that a name of image and I want to bind this to something so I'll say bind files would be equals to the file input yeah we have this red Lin showing and that's because of bind file does not exist init it's bound bind files with an S so make sure that you get that correct L and after the input I have a div and this D have some classes so for this D we want toally move bit to the middle of this square or middle of this triangle here sorry it's it's a triangle it's a rectangle how does this look like a triangle I don't know I've just been seen a of rubbish lately but absolute the first St is absolute and then we say point wi events none and I'll tell the reason I'm adding that St very soon after adding that I'll see again I would say I would say after adding that I would type top 1 / 2 is 50 so top 50 make this full screen so we can see properly top 50 so one / two and space Y 2 and after that I'll say text Center maybe this is too large cuz it's really blocking so Tex Center and left 1 / two as well so left 50 and the reason why I'm doing this because of after doing um top 50 left 50 one neat trick that we can do so I'll show you let me just put in a text say this is a text like this and now what I'm going to do is basically move this div into the middle of this parent div with the relative class so I'll show you now if I save this see this is a text right now it's somewhat in the middle but not really in the middle that because ofed it's left 50% and to 50% actually complet this little CS trick that we used to do we just say minus translate X and x50 so we say translate X1 2 so that be minus translate x 1 / 2 and I save that you'll see it move very close to being in the middle and then we can go minus trans late y1 / 2 and save that and that will be perfectly in the middle I can get rid of this text I just want to use this to visualize and first thing I'll put here will be that upload icon so I say upload Cloud going to be from this F I say class size 10 and I save that we should have it there and I'll say MX Auto that's make on the middle at all times after the icon I'll type div and in the div would have a P tag and this P tag would have shoes file or drag and drop and let's see that let's see the way it looks and not bad but not the way we want so for the P tag we class and say text blue capitalize font medium and text SM save and yeah looks a lot better after that first P tag just as a symboling we have another P tag and this P tag will have image telling the user that we accept nothing more than 4 MB get this class going to have a class of text SM and correct this mistake nice now if you read this text very well you see that it actually says choose file which you can easily do by just clicking here so choose file is check we have this all drag and drop and I you might be wondering that we've not added any drag and drop function well by default if we make a file a type of if we make an input sorry a type of file we can actually drag a media or an image in this our case onto the surface of that input and it will drop the file and since we've made the surface or the area this large so this is about um I don't know how much width this is but this is as um 60 this 60 is 240 pixels in terms of height actually just drop a file into this area and it will recorded that the file has been dropped so I'll show you guys what I mean let's continue after the div covering the two pre tags I would have an if block here and this if blog is basically going to be checking whether we have anything in our file input so see if file input do length is equals to one that means we added something to the file um because we are only allowed to add one file I have a button but not a button from CH just a regular button what the sty to our and in here in the button we have a an if block if block again and this if block will just be uploading and upload loing if uploading is true we have loader two and we import that from Lu F and for two will give it classes like an imate spin to actually make it load see I would write I mean size six animate spin after that div we have an else so for the else it will be upload now come on up for the second time in the room because and does end upload and then I'll put the number of file it usually gives me one but I just want to I don't want to add code it I'll say file input dot length file save that now that we are done with that if block we're going to scroll down so after the closing tag of the form after the closing tag of the form we want to have an if else and if you remember for this form we have if is editing then we have the form then this looks better so you guys can actually understand then here we can have an else if I mean not if else else if image URL exists if there's an image URL and else if image URL we can just have image tag and you can pop in the image URL here and for the class I can just put in object cover aspect ratio or aspect video there the aspect video imine top two rounded MD and with full and after this image I can just say or type else going to take some time for me to actually get used to say type and not see else put a d here and this D would have class class will be Flex item Center justify Center Height 60 BG slit um SL slit 200 rounded MD and in the div we just have image icon an image icon would be from lucit felt you have class of size size 10 um text muted foreground save this now this the way this looks cancel and we have this and edit add an image we have this I mean we actually add an image if I choose this image we have the upload one file there from the button that we did in the form now let's actually give that button some Styles doesn't look good at all on button I'll say class PX3 and um py to text white rounded let's go with MD MD would look nice and BG blue 700 let's see that and see the way that looks now let's pick something and yeah that's coming to together it's coming together now you can just capitalize this and the font semi Bard and pointer event um Auto Now save that and that should look and let's wait for that to refresh once it's refreshed look at and add a file again and see the way it looks and yeah looks a lot better and the reason why we're adding this pointer event a to and pointer event n as I said I was going to explain so where do we have that pointer event n okay we have it right here this is we adding this is because of when we click on these things so for example when we click on this input it's going to give us um a file explorer that's correct but all these components or tags or icons are overing above this section so we also want that when we click on this um text we can also open the file explorer so what we just see is just basically by having this CSS class here that says for this div pointer event none it doesn't have any pointer event so when you click on it basically just pass passes the pointer events to the um parent or to the next element and the next element is this input and the input as a pointer event and when we click on text it would activate the Explorer and as for this that we have the pointer event Auto is because of we don't for the button when we click on the button we don't want to actually have that um ex to open we want to do something else let me click on this upload one file and that's why we add poter event AO now for this button we also going to add a type for submit this is the button we used to actually pass the file to the form actions so now that we done with this The Next Step here will be actually creating the form actions for uploading or editing the image so let's move to that now just before we jump to the server file we just going to remember we are this comments here saying switch the back to force so I'll do that real quick false save and we should have this by default now we can move to our CS file we have all those actions and this as we have update um title we have update description in this form we name this update image so the name of this action would be update image next and synchronous Arrow function in here we get and column is needed here and here we get the events and from the event we can D structure some things so from this crais I can get local from local I can get PB and and I can also get params so we can get the C ID and I can also get the request here as well now I can D structure the C ID from the pams come to the call Braes and say C ID and since we are not using spell ke super forms for the image we're going to have to hand the forms ourself so I'll just type in here const form data and this is C case form data is equals to await request do form data and I'll type const image I im a g e image is equals form data dot get and in here we put the name that we gave to the image or to the form tag which was image and I'm going to type here if image instance of instance of file validating that it's actually a file image instance of file open my try and catch block here I say try catch and the reason why we're having this online because instance off is not supposed to be in C case just use regular instance off and then in the try I would await PB do collection this would be the CES collection and the do update method you get the D by this time it should be C ID as the first argument and second one is the um fields we want to update and we want to update the image URL and we just want to update it with the image that we are getting from the form and then after we can return in craes now not using spell kit um super forms message method or message utility or function we are just returning the message and we display the message using um our enhance action so in here I would say successful successfully let's go successfully updated C image and for the catch it's going to be similar to this but we won't be using a again won be using this message cuz we're not using F key to performs yeah so I'll place this in here get rid of the error I'll repl this with E and instead of returning message I will return fil and F the first argument is not form but a status code and this would be 400 and the second one will just be what you want to return and yeah I return the error message so I'll copy this here get of the double comma and I'll put here message would be the error message and I make sure I'm importing field correctly then I'll save and this is basically all I need to create create or add or edit an image now we can try this out let's just go full screen and let's go back to editor and make sure we save every file so I'll do control k then s make sure everything saves Go full screen one more time now if this works you have to give this video a like promise let's try so I click on add an image and then click on the box click on this camera image would open this and then upload one file ah it didn't work there is something missing it did not work oh no so I'm clicking on the upload one F button and nothing is happening okay so let's check out what is happening okay so the image form back to the form yeah and this time I know what's happening so what is happening is we are expecting this prop of image URL but we are not guessing it yeah so you see that we have this red line if I scroll down enough okay so we are not having any red line here but the image are there it is red line so it's expecting the image URL and we not sending it we forgot about that little detail and our little thing did not work so I don't get you're like you can keep it all right so let's fix this we'll try the like thing again we'll try later I'll make sure I get that like from you so you see here we have this course and in the course we can get the c. image URL that's all we need here so I'll just type in image URL is equals to course do image URL make sure I save that and now let's test this add an image select this image upload one file and still didn't work the way we expected it to work now let's check that out for the second time what is happening this time so moving back to our image form and if we actually click on this cancel button in the browser you see that the image was added but when we uploaded the image this States remained so we want to toggle the state and we are going to do that is by expanding or extending this use enhance action so I say equals to craes and in here I just have an arrow function and I'll say uploading will be equals to true now this is when the you just clicked on the um button you just started the action so once the action starts we set uploading to true and then we return a sync synchronous Arrow function and here we can D structure two things that we're going to need we need the update and we need the result and in this CES I can say a wa updates after we gotten updates I'll say uploading would not be equals to false and the file input would now be equals to no and if results was given another if the result DOT type is equals to failure and I to do a toast notification I say toast and that be spell dot error and in there I'll say result do data Dot message dot to string because to to accept a string and if you use it without that to string meod is getting through an error and I'll say if this was undefined so all an empty string and yeah I'll just put my dollar or my question marks in front of them and after this I'll have another if so under here I have if we result do type is equals to error my braces this should be in a string I just P that there but this time it's not going to be this it's going to be result do error do message and now for the last one we check if result DOT type is equals to success in here I see to do sucess pop in results do data do message dot to stream string method or an empty string and it should be type and I spelled my error wrong just sure I double check everything yeah so after this um if block covering all of the other if blocks I'll just pop in here um in validate all and invalidate all it's going to be from appnation but I'm not done so after this was successful I also want to toggle the state as I said so I canot use that toggle edit function that I have and now when I save all of this and try this out again let's see what we get now we actually have this image added or we can edit this image I click here I'll click on a new file let's cck with go with this open upload one file and Bam what work works the way that we want it to work now let's move on we are done with the c title the C description and the course image let's move into the editor to check out what's next and if I go to the page I would see that we have a category form next so let's build the category form out open up my Explorer the components folder creates a new component called form do Felts poping the little snippet this is the category form and going back to my P just f file I can just pop in here C gory form import that and I'll remove this comment here we don't need this anymore any and I'll divide my screen I'll save and we should have that pop after this C image okay we actually haven't saved that file so let's save that file as well now we have this is the category form I'm moving back into the category form component we can start building out the category and first thing we do is get rid of this text here need it anymore and in the class attribute we have Marin top six give this a border say be muted rounded MD and p 4 right now you should get that this T is pretty much consistent with all of the other components that because of they all have the same background and the same B radius and same padding and so on and so forth after done that we can say div inside div and here we have course category this D will have class and this class would be font medium Flex item Center justify between and I can put Shan's fa button in here I just say this Auto input would work and it did now in this button component going to have to toggle edit and well we already have this code like written over and over and over we can't just keep rewriting these things so we can just basically copy so I'm going to the description form and once now copy is Luis F icon we're going to be using because we'll be using this icons on this component as well and now to talk go back and forth like the way I said earlier and just Ty control PP or command PP in um I believe Mark so we've gotten that we also need to get some other things from here like this whole button we can just copy it and now we need this tole edits so I'll scroll up and I'll get tole edit and is Ed is editing and I'll past this here and what else do we need all right we'll leave that as it is now when we need more things that we've written before we would copy them now coming out of this div I will have an if block and the if block is going to be checking if is editing this is false and if it's false we have a P tag here and the P tag would have the category name so just call it like this for now when we added the way to F the categories we'll put the category name here and tag would have class and the class would be let's use Dynamic classes so um I'll say CN I import CN from li/ and inside CN we have the first the base St so we text SM margin top two and after that can pop in here the optional styles that be added based on a particular value and would ignore that just for now I keep on going so right after this um P tag would have else and this else will have a form this form will have a action of updates category would have method and the method would be of post and remember we always like to announce our forms so I use the action use and and and I'll put like a class say wful space Y6 after all of this just come in between the form tags and click enter all right so before we continue I want to correct the spelling error that I have here this a category like so and now we can copy the form input from the description form component and I'll paste it here and in the form tag I can just write form dot field and here in form. field you're going to have a form do control and this form. control would have in here a select component so before we continue let's initialize s kit super forms what we can do here as well is just to copy this that we have here instead of rewriting it you can just copy and modify to fit this component first of all we're going to have to import super forms we have to import the client I'm we going to have to create the category schema so move into your schema file and here we have a category schema so I just duplicate sorry duplicate the so yeah I will just duplicate the description schema and I'll write atory schema and I'll pick the category now move back to my category form component in here I'll replace it with my category schema make sure I import that and I also want to get data and this will be a props a props and I can just copy this one here paste it here and we can just also copy the inputs as well let copy this will UT and replace it with this one that we have here and the toast as well import the toast and in here we have a type of category schema instead of description schema so just after this form that we are structuring I can get the selected field so I'll say dollar sign column selected value would be equals to category and now we going to have to create another prop called categories so I'll come above here we have prop and I have export LS export let Cate Gories and categories is going to be of type category remember we created a type so just import it from our leave SL types and to be an array of categories so I can scroll back down to here and I can have categories dot find and we'll get the category the single category and we check if the category do ID is equal to form data dot category and here I would question mark do name and get the name like this that's how we get the selected value and it's reactive after getting the selected value we can get the selected category so dollar sign column selected category and this going to be equal to do sign form data dot category now if the form data that category exist then we just open our CES here we say label and the label would be selected value and the value would be to form data dot category and whatever our else and if it didn't exist just be undefined like so now in here this B tag where we have the CN I can actually add the class that I want if the category does not exist it's going to be very similar to the one we've added in the past text muted foreground this would apply if exclamation mark data do data dot gu it category and this the category name Will remove this and we put our Co Braes here and say selected value if selected value does not exist would have the text no Tory now coming back down to our form to fix the errors that we having first of all you notice that we have using this action using nouns but we actually not using the one from s super phones cuz we have this red on the line and that's because of we are importing the one from um stal kit we don't want that one so I'll just remove this and now they they don't have conflicting names and we can use that one and in the form field here you're going to have to add the form and this syntax is basically the same as doing this form is equals to form but just it allows us do nice things like this and I've added the form I also have to add the name and the name you only have one name one um field in this schema which is category and in the form control we have to bring out let column 83 R attributes something and in here we would use as I said the select component so let's import the select component first first of all to move to the top of the file and now say cni select so after importing that I'll come down here inside the form control I'll say cnx or type cnx and select and we have this snippet to work with forat that properly and now the first thing we have here is the select rout we can just add um the selected value so I say selected would be equals to select thir category and after that I'll type here on unselected change so put in our Arrow function here say e or let's use V to represent value and V and if V exists then we want in your the last sign form data do category to be equals to V do value now for the select trigger I want to pass in the at RS but here I actually want to spread it so three dots at the front spread it and after that we move to the selected um value yeah would have this place so that I change it from teams to select aor and move down to the select content here we will have a class weight of 60 and before I forgot I forget let me get rid of this class here don't need this here and here we Loop over the categories I'll be get from outside this component we use the each block I just type in here each this each categories as category here would have the select and we shouldn't have deleted all select items just I'm got one but whatever say select do item and yeah nice and in this select item we have some attributes say the first be the value and the value would be the category do ID and after we have the label and the label will be the category do name and after here we just move inside of the middle of the tags and put craes and pop in the category not name and yeah that will be all for the select component and we can move down to the select rout and after the closing tag of the select Roots I'll put in an input here and this is the input that will actually send the values down to the form action so in this input I'll make this Ed because I do not want to see it I just want to make this something that I used to hold the values and send to the form actions and I'll bind the values so let me add the name the name would be rs. name and I'll say all right bind value would be equals to dollar sign form data dot category and under after the closing tag of the form contol I can put in our error so I'll say form Dot fi error or errors should be errors yeah like that outside the form field but still inside the form tag we want to add our form button and I can basically just copy the form button from here so we don't need to rewrite these things every time copy and paste that and make sure that loader two is imported correctly and we save and now once we save that we will probably get an error because of we have not added the category prob that we are expecting the data so we need to um return the category from the category form from the server come to the server for just like we returning title form description form we're going to return the category form as well just duplicate this sorry and I would rename this to iory form and in the Zod adapter or adapter I would put in here category schema and make sure that we import that from the schema file and I will just simply return category form M back to our page file in here I'll type in here data would be equals to data dot category form and we also need to return um inputs or pass sorry pass categories as well so say categories will be equals to data dot the categories and I will save all file with control K and S and let's see how that looks in the browser and here we have the category components I click on edit okay so the text is still edit description it shouldn't be edit description it should be edit category let's change that let's pray I can spell that correctly in one go and Y all right now you see the edit category I click on edit category and now we can select the category and we have all the categories being feted from bucket base and populated here and I just choose um computer science and when I click save nothing happen because we've not add the action so let's do that next let's add a category form action so moving to our Ser file and scroll down to after the update image action we want to add a Cate update category I mean action before we continue let's check the name we give to the action so the category form and in here we give this update category so just so we can be sure comma update category and you here put an asynchronous arrow function and in this will get event you know the D by now in fact I don't even need to keep seeing it I can just be moving along and you at this point should know what to do so I'll get rid of request I don't need request here and yeah we need the C ID so I'll copy the C ID the we popped out the C ID and yeah we need to check for if the form is valid so I'll do that yeah as well copy basically copy and paste the parts that are are going to be the same so we don't just write things over and over again I can see try and cash block and in the try would have a with PB do at this point you should know what to write targeting the CES and I using the dot update method and we updating just the category so first put the course ID second argument we say or we would write form dot data and there's going to be a little issue here because of we are using description form instead of ategory schema need to just make sure you change that and for the catch it's going to be the same thing but before we go to the catch block let's return a message I can copy this as well because it's the same thing in fact I'll copy the message and the cat block itself and I'll just paste this here and instead of writing can and instead of writing successfully updated course description I'll change it to successfully updated course category and I'll save this and we're having this allot I don't know why we need this Aller saying changes you made have not been saved reload all right now let's check this out so edit category computer science save successfully updated cost category nice now let's move on the next component that we're going to be tackling is going to be the price form so we're going to skip the shapter forms for now and later on we build it but for now let's tackle the price form open your Explorer and create a new file in the components folder called price form I just pop in my little snippet there and this is how your should look like and in the div I can just write this is the price form component I'll go back to the page and I'll replace this price form comments with the price form component itself and I can get rid of the comments here move back to the components and let's building up the price for remember a lot of these components are the same so we really can just copy the description form CR a contr c go back to the price form component and just paste it replace it everything that we have there then we'll modify this to fit the price form component first thing we need here is a price schema we move to our schema file and just like the we've gotten the rest of the schemas we can get a price schema so I'll duplicate this and got this price so what I'm doing here is renaming this to price schema and then I'm from the cost schema I'm picking the price just like we did for the title description and the category as well now that we have the price schema we can replace everywhere that we have description schema with price schema so what I'm doing is just typing or tapping control D this will copy all instance of price schema and I can say of description schema I mean and I can say price schema like that and I want to change this to edit price I want to change description here to price as well and instead of just coming and saying data do data do price this price is going to be a number and I want it to be formed in the currency that's the person building this project shows like for me I'm in Nigeria so I want this to be formed in NAA for you if you might be in Indian uh United States you can format this to the currency of your country so what we do is create a little utility function that would help us to form out the currency so go to your utils file and in your you file just go to the bottom and would export a function and call it format currency and this function will get the price on number that we want to for so n would be of type number no number number and then first of all we want to check if that was a number so say if is none and is n is like this and we put number in here and we return so we are saying if it's not a number so this is just L to Something in JavaScript is N means is not a number and if it's not a number we just want to return it that mean it's of any other data type except number and we we don't want to work with any other thing except except number so now if we've been able to run that check we can now say return that means what we have is a number we can now return new until DOT number format and in here I'll put in for me this is e n NG and I put in the options which the first option I want is the style and style should be currency and the currency should be n GN you can go below that and just yeah see dots format and I'll pop the number yeah n so save this file and we'll move back to our price form components and in here in here I can just so instead of having data. data. price since we'll be using price in couple of different places we can just say price is equal data dot data dot price and we can put this exclamation mark at the back so tell TPT that it would not be undefined and here we can just say can get rid of this and I'll right price so I want to check if price exist first so if price exist and I now use my format currency function and I'll pop in the price and if there was no price we just say no price for the action and the form it will be update price and for the name of this form field it would be price and the type of form would be using or the type of field we' be using is an input not a text area so I'll just replace it with everything that we have here and I'll get rid of the text area and I make sure I want to import this input uh yep and I will change the place that to set a price for your cost and with buy value it's not be description this time time it would be price and we should also get Auto completion at this point yeah so it should be price and we can say type just for constraints we say type number and we can also give this a step the step equals to 0.01 save that should be all we need so let's control K and S to save every other on save file because of looking at my Explorer I can see that we have some unsaved files there and I'll just divide the screen and let's look at what we have here now so um scroll down and to the sell your course parts we still don't have any components popping up there so let's go back to the page and see what's up all right so we having a bit of error because of data is missing in type blah blah blah what we have to do now is go to the server file of this page and just the way we are returning all the other forms so we are returning um title description category we should also return the price form as well I'll duplicate this I say price here and for the schema I'll use price schema instead of category schema price schema and I'll make sure that I import the price schema so if the import doesn't work for you you can just come up here and type it inside the qu brais for the input of the schema dot now it uses JS sometimes it does this little thing where it puts JS you can just remove that doesn't actually we're not using GS in this build at all now we have the price the price form we can return it here like price form and we can create the action to actually mutate the price so I can screw down here and have another named action and I'll call this update price because that was the name we gave to it syn and here we get event and from the event we can get you know what we can just copy here at this point it's basically the same thing comma here so that we don't get that error and I'll paste in what I just copied now and we can do the super validate and other stuff let's basically copy the whole thing for the category and just change it to fit our price action so yeah we're checking if valid if it's not Val return a f and here we want to Target this here and mate the price so this would work even though it's literally just copying a code from the upate category directly it to work the way we want it to work and that's that's beautiful only thing we need to change here is just change the error um the successful message and the yeah and we good so we can see successfully updated cost price itself category and that's that's all for the price so I'll save this file and I will open our browser so that we can actually test this out and we still have an error now we having a 500 internal error and if you remember we actually haven't returned anything for this price from prop so I was just say yeah um data is equal to data Dot price form we don't need this white space we have here save and let's try that one more time and it appears here and we see we have C description here we actually haven't changed everything we still need to change that part it's not supposed to be description it's supposed to be price so we have course price okay let's just double check again make sure that everything is nice and all right let's test this out so I'm back here changes to cost price I'll click on edit price button and we you see that we having description here again let's just signore that for now and let's no no we're not ignoring it let's let's change it let's change it now before we try it out are you kidding me so yeah description we should be price actually need a um a label at this point because of we have the label up here I feel like we don't need a label but we can keep the label doesn't have anything all right edit price now nice so I can just see 1,000 and I'll save as you can see we see successfully updated price cost price but it doesn't reflect here we still have no price uh what is wrong we basically just copy the last thing so it should work the way it was supposed to work let's just double check this one more time so if we check our dashboard you notice that the price doesn't actually change so this is coming from the server so let's try this one more time Mi 100 sa it tells us they successfully updated the cost but we go to our dashboard and refresh this the price still was Zero hasn't changed so I know now that the place I need to Target is the plus P CS4 and let's just now nice so we have the category schema all right so it's not supposed to be a category schema this should be the price schema little little things like this will make you sleep on finding bug that's the one the bad things about just copy and pasting without like rereading and rechecking every single thing because of little little things that you might miss up like this can keep you on your decks for hours and then just because you didn't change this and then spell ke doesn't show like doesn't show like pinpoint errors so you doesn't you don't know where the error is coming from your browser doesn't tell you where the is coming from and now you are you are just basically lost well let's save this make sure that that is saved and we can try this one more time go back to our app and let's try this out 1,000 and Bam works so sucessfully the cost price and we have the price being formatted in my currency so that's beautiful now let's move on and create the attachments so we'll leave the chapters for last let's create the attachments but before we start writing code let's create the collections for the attachments so we create a new collection in our admin dashboard we call this attachment did I spell that correctly IU attachments and we'll give this some new fields the first F will be given it a plain text we'll call this name and yeah we give it another one this one is going to be a relation and it's going to be single and they select the collection the collection will selecting will be the courses and we will name this course the course that this attachment belongs to that's what we creating and then a new field and this time we'll just give this a URL EX attachment is a file so URL and we call this URL and we just give this a little constraint Say Non empty and create like that nice now let's go back to our editor let's move to the page file let's go where we have the attachment form comment and yeah would get rid of this um comment and put in attachment components but we have not yet created the attachment component so let's do that first in our components folder new um not a file a new I mean not a folder a new file attachment form dot SP and this is going to be very similar to the image form so we can just take inspiration from that and basically copy the whole thing so contr C contr a then contr C to copy every text here go back to my attachment form the felt and control V to paste it all there and I will just change this and mutate this to fit um the attachment form component now what we can do is go back to the page and replace this comment with attachment form and attachment wasn't spelled correctly but that was a long streak you can't lie I went some some some few words without me spelling anything so okay so this attachment is still not Spell correctly where am I missing a t t a c h e there's not supposed to be any and still telling me no suggestion so that's basically because I probably didn't spell attachment here correctly as well yeah I have e as well it should not be e yeah that's not attachment okay now this should work it's still telling me no suggestion so I'm basically going to import this myself come below the price form and just change the price to attachment form should up letter A my bad all right now this should be imported attachment form is not defined it is it's defined I've imported it now I can go back to the attachment form do felt and I can modify this to fit the attachment form component so the first thing we're going to do is change every instance that we see image to attachments of file so this will CA let's use a small letter a CA attachment what is this e always doing is it you just comes there I don't know if I'm typing it just appears there so now we'll be checking if not not if image URL we'll be checking if attachment so let's create a um variable let say um come above here see it's going to be a prop so let's just export let attachment and attachment is going to be a type of um array of attachment remember we have the attachments type already in my types file so let me just move to my types file we have this attachment file type here so we can just use that one here and I can just say attach the E again e again attachment and would import that from types and put an array bracket at the back of it and we can this attachments here we can see if um attachment uh this is not cap letter A attachments dot length so now checking if is equals to zero or undefined or any F value that's why we have the exclamation mark in front of it so I say that if there is nothing in this attachments the now to should add a file and else I'll say edit file and I can scroll down here and I can just change the action here to create [Music] attachments just leave that as sarch scroll down all this I'll leave this the way it is this doesn't have to be changed scroll down here and and yeah this is pretty okay now we have image here as well so we can change this um image part well we can also add a little text to help the users know what to add here so before the form ends I just have a P tag here and I'll say add anything your students HD might need to complete this course Reon why I'm stating this so they know that's not just image that allowed pretty much any file under 4 M will be allowed to be uploaded Here video or file an image even audio is allowed so I'll just type that there like so and I'll give you some class let's make that look a lot better see imagine top four text muted foreground you know the D by now and we can just say text extra small and this else if would be attachment dot length so if there is something in this attachment I don't want to show the form initially so I'll just have an is block and this each block I'll list all the attachment that are in the attachment um um record for this course see is attachment and I'm I'm going to basically do something nice here which is called optimistic updates and the reason I'm doing that is give the user a feeling of just quick UI and I also want to show you how to do it there's no real need I can just keep on using the usual um requests we have been doing doing it but I want to show you how to do optimistic update and show you how easy it is to do it in spel so what we basically going to be doing is just updating the UI optimistically so when the user makes any action we just instantly let it reflect in the UI so if a user for example if a user deletes an attachment which is an action that user will be able to do we want that attachment to disappear immediately we don't want it to get a response we don't want to wait for a response from the before we delete the attachment and like show a loading spinner or something like that now we want to give the user instance UI update and that's why it's called optimistic UI optimistic optimistic update so I'll just come above in my script tag and I'll create some variables I would need so let deleting ID would be equal would be a type of let's give this a type of first string or n and it will be equals to null by default then we have another variable which should be let deleting should string be an array of string these are the deleting that or the attachments that we are deleting currently or at that certain time so now that we've created these two variables we can use them to create optimistic updates and I'll show you how easy that is so scroll back down to where we have the is is block for the attachments and in here instead of just looping over the attachments like each attachments as attachment and then having like a P tag here and then just popping or let's say whatever P tag or um something to preview the attachments just have IDE basically like that what we do is we want to filter from this attachment so we'll say attachment do filter and want to filter from it the attachment that are not included in the deleting array so if it's in the deleting array currently we want to remove it immediately it's in theary and that's how we're going to create that effect so I'll show you what I mean so I say attachment on filter and exclamation mark then we say deleting which is an array that we created do includes [Music] attachment do ID so now we are checking if the attachment that the current attachment ID is included in this deleting array this deleting array is going to be an array of strings and more precisely an array of IDs so if this ID is present in this deleting array we don't want to display it here that mean it's in the process of being deleted and because of we optimistic we I've already concluded that it's going to be successful to optimistic update optimistic UI whatever so I can now say okay I'm having a little bit of erroring attachment on word on the F that's because I did not spell it right we have there again so you can get rid of that and I can just check if this is basically all we need to do basically but right here what I want to do is just put in a key so in Sp can the key by just saying bracket and say attachment. ID and the reason why I'm doing this because I'm going to be using some animations here or some transitions now in the blog I can say div and this Ste is going to have class this is where we're going to display the attachments that we have so Flex item Center P3 with full Gap X2 BG Sky 100 border sky um 200 and then to actually make this work we have to add border then text Sky 700 make this rounded MD and mb2 okay now V what is V border and to add transitions in spell is very easy we can just say in and we can use the fly action froms f/ transition and we can use another one for out column and these are basically just felt actions that add animation JavaScript animation to this element so I can use outslide and because I want to add some options for this fly transition I can just equal CRA this two CB I say the Y this 20 like that and in the div the first thing have here is a file icon the file icon is going to be from Lucid SP we can give this class of size is equal size is four not equal to-4 and margin two say FX string zero and after the files we have a P tag and this P tag would have the attachment dot name this P tag would have a couple of classes as well let see text um exra small and line clamp one and what line clamp one does is if the text becomes really large it starts overflow this element is just going to clamp it and put like the dots at the end so a very nice effect and we can save this now we've just been writing and writing and writing we not even checked how it looks in the browser but right now it's nothing that's going to show on the browser in fact I think if I save this and arrow should show yes and that because of the attachment form it's not sorry it's not currently accepting anything that should be accepting so let's fix that what we see here or right here is so remember we have an attachment prop in the attachment forms component so we need to give this a value data dot C and if you go back to the types you see that we have in the course we can expand and from the expand we can use back backward expansion I usually C back relation same thing but we can expand for the attachments and that setting cost and get the attachment of f setting course so that what we're going to do now and if you go to your terminal that you're running pocket base you might notice some certain warning or notification that keeps popping up which is um this say attachment cause expand format is depr deprecated and would be removed in the future consider replacing it with attachment umore viore course so this is for the current version of pocket base This Is How We Do the backward expansion on backward relation we use VI and not this expand keyword anymore but for this course since I've created this using that format we are going to just continue using it but in the future we'll be using the vi pattern or the new pattern that they've created which I believe is far more better and allows you to do more nice things like futuring and other cool stuff but for now we're just going to keep on using this format until the next time we create a new project with pocket base and we use the current one so I'll say data. C and yeah I can get expand so you look here expand and from expand I can get the attachment course so if I come here I see attachment course here click enter and it gives me in bracket notation and I can just say because of it's possible this is on the f I can just two um question marks after that and see I'm just typing a empty array bracket and one thing I want to do is because of again this can be undefined in front of the course I'll put a question mark here and in front of this qu of this bracket notation I put or question mark and Dot because of I want to satisfy condition that this could be Onin and by doing this I have this little error here but should disappear and we are still having this underline in the attachment form and that's because of it's expecting image URL as well we do not need image URL here so I'll get rid of this let's just check we don't also need this comments here as well okay we was just saying switch editing back to First what was that saying first and editing is in first I remember we made that comment in that component so when we copied it here it came here as well just double check that we don't have any instance of image or anything funny thing yeah C CAU you in the act and you were somewhere so get rid of this and yeah we can save can save this they should work fine and just ignore the St lines just just ignore the rad L pretend like you don't see them as is a pain so let's go back to our browser let just refresh and let's see how it looks now and it pops up now we have this cost attachment components here and we can click on add a file we click on add a file we have this and when we click on this we just have here in the pictures and click on an file so say image and open and it says uplo one file this would not work clearly because we don't have the actions set up yet so next thing we're going to be doing is setting up the actions let's move over to the server file yeah and we'll create a new action called create attachment I go one second without Miss spelling something sync and can get the event and here we can D structure a couple of things so it's going basically the same thing I'll just copy it here and put it down here and you can get a c ID as well well from the par so copy and paste and now we can say cons form data is equals to await request now we need request as well so we can structure request from here come here and just the structure request now I can use requests I can request dot form data and C case nope now we can get the file we can get the file by just writing const file is equals to form do get just use form data I mean so we get form data from here so we can use form data dog the get method and put the name of the file which is file and we didn't actually give this attachment form input the name of file we still have image which is the one we used for the image component so we change this to file and here we have this image find be want this to be file and here we telling to accept images we don't want this we want it to be able to accept every type of file so we can just get rid of this save that we go back now we can continue and after we've gotten the file yeah we can now open our TR and catch block the aror part of the cat block we can just copy and paste it because it's the same and the tri block what we do is our wait PB do collections this time we'll be targeting the attachment collection you just remember we have an attachments collection here so let me show you we created an an attachments collection here and saes the name the cost and the URL so you can go back we have the attachment collection that's what we targeting then I see create and weing collections instead of collection so not collections collection so create and in here we pop in the name for now I just write whatever that's not how to spell what that's not how to spell whatever now if you're terrible at um spelling like the way I am there's this um nice V SC extension that helps me correct my spelling so it's called I think code spell check it's a vs Cod extension and it would help you correct your spelling let me just check it real quick if I can bring it out yeah this one right here code spell checker very very nice extension so let's continue the name then course yeah we just put the course ID and the URL would be F and then here we have this error saying message blah we don't we not using super forms for this um for this component so we won't be using this format the format will be using the simp Mouse we used for the image so instead of writing that by hand again we can just copy and paste always better to copy and paste uh come right here and P this yeah all right and if this is successful in the tri block we will just send a message we say return message and we WR successfully added cost attachments let's save that and let's check if this would work in our application all right so add a file click let's choose this camera image open and upload one file and the request resource wasn't found so there was an error so this error is going to be from pocket base so let's check out all right so I think I know what the error is well the error should be the API rules so if you go to my edit collection go to my AP R you see that all of this are locked so only the admins are allowed to make these actions or creates um read view update and so on so what we can do is set API rules the way we did for the course you remember in the course and the um categories as well we had API rules added so as you can see to create a course you need to be authenticated to update a course um to delete a course need to be authenticated as well and for the categories as well but what we can do here since we don't want to waste a lot of our time just writing rules cuz the rules you can get pretty lengthy if you're trying to cover up edge cases we can just say um unlock and set custom room so when we just unlock and set custom room now we have this comment saying leave empty to Grant everyone access and that's what we want so we just want to Grant everybody El this is not safe or it's not the safest format of doing things but so that we don't spend a lot of time just writing rules is best we just get Grant everybody access so I'll sa the changes like that and then I'll try this one more time okay nothing popped up there some reason open and it's not popping up anything me cancel and try one more time for some reason it's not popping up that button ah now upload one file and the request results wasn't found again so let's go back to pocket base and we check this settings now we go to our logs so let's see the error that is been created here this is the um one we made and you going to see collections attachments and for the records that is the data URL so that's correct and the error saying the res request isn't found but the detail is SQL no Ru in results sets no rules in result sets what is that supposed to mean let's just check that out okay let's check our code this time make sure everything is correct attachment screen so sometimes these things happen and you just stuck so I'm going to just debug this right here I'm not going to edit this part out so I can show you how this process might look like for most of you so what I'm going to do first of all is make sure I'm guess in the file so I'll log out the file and I'll just comment out this try and Cat block so make sure I'm getting this file logged out so I'll save this and move to my browser and I have the F let see way that looks like okay so it lose forever but yeah the file is been um got in and is brought down to the action to the server so when we are we know that the error is not coming from here so let's uncomment this TR cash block so the error is from here this part so pb. collections. attachments create this is correct code am I missing something I don't think so this is this is correct everything is correct could it be my spelling of attachment let me just check this again yeah that's that muches let's see if it matches the collection name nah it doesn't match the collection The Collection name has an e it has an e it's my spelling yeah I knew something was wrong so can be edit that collection name I don't think so I think we're going to have to create this collection again uh okay ah we can we can actually right so get rid of that and save changes confirm yeah it's cool and yeah let's try this one time upload one file and this time we didn't get any um notification that's because we didn't save this when we uncommented it so let's save it and let's try it again all right let's try it one more time add a file click there let Pi this file and upload one file and field to create record that's the error this time so it's different so we're making progress when the error is different you're makinging progress so refresh that as you can see it filled it did fill to create a record and let's check again what could be wrong the second time so um I creating a new record yes we adding the name we adding the cost we adding the URL now what are the fields that expected from this this is expecting the name the cost and URL so the same Bic thing just make sure that they are spel correctly all right so what could causeing the error this time let's try this again I don't think there should have been an error and I click on it it doesn't catch create [Music] record and I'll just go to the logs yeah missing required value all right so we are missing one required value so what is the required value that we are missing that is a question now cuz I don't think I added any extra things here I just added the name the C and the URL and the one that I know that is required is the URL and that is being added here if I'm not wrong right here like so so it's saying that the URL is missing whereas the URL is not missing so let's just make sure that we actually let make sure that we actually save this for well cuz maybe this this thing let's see this properly I can clearly see that saved but just because of I'm starting to think I'm running M little by little everything seems correct here from my side and I don't know why it will showing um fi to gra record so let's just save this properly and let try this for more time all right if it doesn't work this time then I'll pause the video and I'll go debug it and I'll come back cuz I don't want to just show this I make this video longer than it's supposed to be because of an error that we having I'm test this out add the file and I just add a image up file and we get error right so what I'm going to do now I'll pause it I'll debug it from my side and then when I find error I'll let you guys know so that if you also having this error you can know how to fix it so I'll see you on the other side all right welcome to the other side and I found the arrow and you won't believe what it was okay maybe you might believe because at this point you realize I make a lot of silly mistakes but what the arrow was was this field is a link field if I'm not wrong and we can use Link Field for a file and that's the issue that we had and that's also one thing that I noticed about Pock be and all this very niched tools is that they don't have like very good Arrow handling I say if I did not come here and evaluated and inspected everything one by one I would not have found out that I made this mistake so it's very hard to debug sometimes well that's just one downside to using all this I'll say very small um user based tools whereas it's not like extremely popular and they trying to give it the best of everything but p is still a great tool hands down I don't know what I'm blabbing about let's just fix this it was my error so remove and then we remove this and create another one new field and this time we won use a URL click on the URL what we need is a file this would be called URL and I can see single multiple yeah multiple I think multiple is good we can go here and say no restrictions blah blah blah n MC and save changes confirm try this one more time upload one file and it successful now we have the name same whatsoever but I don't want the name to be whatsoever I want the name to be the name of the file so I will say here file. name I save and I'll try this again edit file add a new file this time it should give it the name drones so let's see taking this time and yeah successfully added cost attachments drones. PNG that's okay we can get rid of the PNG part as well but I think this is okay like this so I'll get rid of the whatever part come to my attachment I'll refresh here you should have two we should have this whatever yeah I don't want this whatever so I'll just delete this I refresh and we should have yeah I'll refresh as well and we should only have the drones that PNG now the next um point of focus would be deleting the um attachment so we're going to create a little form action as well but the form action will not be accepting any input just be a little icon and then when we click on the icon it then sends the ID of this item to our server and then we delete it using that ID so I'll show you what I'm talking about all you want to do now okay because of typescript um file is possibly null we can just make sure that file is not know so see if file yeah t is actually very nice to it make sure make sure that you don't make errors so just make sure that file was uted and we can go to the attachment form do spel sorry the attachment form do felt component and just after this name in the um each block where we have where we are listing all of the attachments just after the name I want a form and this form will have an action of delete t M so let's get this the method now so just give this a method of post and we use um enance from spell / kit so use and ANS and we import an an from spell SL kit like that okay it's probably already imported and can basically see immediately we click on the icon button that mean immedately we run or invoke this um form action I want to add the ID of this particular um attachment to my deleting array deleting will be equals to deleting I to spread all of the deleting that we have before and I want to add the attachments. idid to it now it's added this L array so it would be removed from this list immediately now I can now say to do successful now I don't know if it's successful or not but I'm just um being optimistic that it would be so I'll just say successfully deleted cost attachment now we can return a syn and from here we get with just the structure update and results nope we can wait update and we've got an update say deleting would be equal to deleting dot filter the ID because each string there's an ID and say if ID is not equal to attachment. ID I can use my if block for the results I can basically just copy this part I don't want to type it by hand over again come on I push this here I see if the result type is failure and I'll just pop this here I say if it's Error now publ this here we don't actually need this part for Success so inside the form oh let's just get this one class the class will give this would be margin left Auto I want this to be pushed to the extreme right so imine left or two and in the form you have an input this input is just going to be used to move the ID to the server is going to be hidden so I'll say um type of hiden and the value so I get of the um name and all we need is just the ID the name we don't need the name sorry I made a mistake we don't need the ID we need the name so it's the name we used to identify it the ID we need the name so the name we just call the name ID and value would be equal to the attachment do ID and this type is giving us an error because of you have it twice can get rid of this type of text and say type is equals to eing and after we've done this input I can just have a button here and the button will have an icon of X and we import this icon from l f just be a class size four and the button have a class over just get an opacity so when you over it have an opacity of 75 and this [Music] transition Colors Let's Get transition or so so the OPAC is going to be affected as well and that's basically it so I can save this and let's test that out it won't work if you know what I mean because we haven't created the action yet but let's look at how the UI looks now so yeah we have this x right at the extreme right and click on that X want it to delete like that so just as the way it removed it from the um list that's what we want but when we removed it from the list we add this error because we don't actually have an action that is doing that mutation that's why we add this error so I can just refresh this for the arrow to disappear and now let's create the action and go to our server file and yeah I'll say delete attachment I'm use a synchronus we can copy all the things that we need here so we need all of these let's get event from here first then let's paste out of that and we also need the ID sub con ID is equal to form data. get and what we named it was ID and we just say a string so the test goes away we can now have our try and cash block here and the error part we can just basically copy the catch block for the try this time we're going to be using the delete method on the collection so I wait PB do collection and the collection that we are targeting is the attachment and we use the delete and what we need to pop is the ID of the record that we want to delete so I'll just say ID yeah CU we have the ID right here already and we don't actually need a cost ID this time so get of this and get of the param as well when we've done that we can just return message and I want the message to be identical to this one here I have yes just LED C attachment so I'll copy this and I'll paste this here and I'll save this and now we can try out the delete attachment functionality of the application go to my browser for that to refresh now I'll click on the x button to try to initiate delete method and it disappears it tell sucessfully deleted C attachment and it did it almost instantly giving us that nice real time filling so that's basically the whole gist of optimistic updates just very very nice and clean you are I really like it so I can just click here immediately and you can see the transition very clean and one other is that we don't actually need this message here actually so I can comment this out it's actually running the stuff because we not showing this message but using the one from here start cat here so we we don't need this one here so can get rid of this save and you'll see it actually still gives us the message so let's add in file add a file and add this upload one file successfully uploaded cameras PNG and when I delete this let me just gra this ER first of all of this I mean notification sorry first of all and then I delete this and immediately successfully deleted CA attachment and yeah very nice smooth transitions there now that we've dealt with the attachments we've done the price we've done every other component accept the cost chapters let's tackle that now so begin by creating a course chapters typle component now we can move to the course chapter go to your editor open your Explorer components creates a new file called shapter form get of that chapter form f o rm. spell and you just say this is the shapter form I'll go back to the page file and I'll get this comments VI the attachment form and I come to the chapter form I put a new component here chapter form the one we just created and I'm make sure this allo inputs like so and I'll get rid of the comments now I'll save this and I'll just contr KS to save all the other unsaved files there as well and I'll check in my browser if it reflects and it does this is the shapter form now we can start building out that form get rid of this sfc to give me the little snippers that I use and this component is going to be very similar to the title form component so you can go to the title form you just copy everything replace everything here with that and we have to change a couple of things first thing here will changes this name it's going to C um chapters yeah we can leave this like SE Right add add chapter a shapter and for the action and the form will say is if is creating so I want to create a new um um variable called is creating instead using is editing we use is creating we can use is editing there's no problem with is editing they still work the same way but in creating a shapter we are not editing a shapter in this form we'll be creating a chapter we are not going to be able to edit this um the chapter in this form so if you want to edit the chapter we have to go into that chapter itself the chapter page and then that chapter well in this form we only going to be creating that chapter so this naming convention does not work for this case scenarios that's why I want us to change this to creating to be more correct so I'll change every part I see is editing to um is create that's better so just say toggle create so create t o g g no o above um is creating I can create a props here say export let chapters and chapters B of type an array of chapters and remember this chapter created in type so let's go back to our types file you see we have this shapter here so this is what we want to use you can just use this and it's not important for us the auto input isn't working so we can just import this ourself the part is import craes shelter from from sign leap slash types that's all and now this would be an ARR of shapter so use like that and for the if BL here we change some things we don't want the else to be where the form would be we want or copy this I want to make this to be above I'll tell you while later so I'll say if it's creating so the exclamation mark will make it not so I've gotten rid of the exclamation mark so I'm saying if it's creating I pop this um form here and I want to change a couple of things in this form first of all is the action and yeah they say update Title we want to change this to create chapter and we want to change couple of things like first of all the placeholder I just say EG inro duction to the cost and yeah here I say save I will change it to create and after this if we have this else but in this case we have an else if and the S if would be S if chapters do length that means there is at least one chapter and I'll put the chapter list here the chapter list is going to be a component itself so I'll put a comment here we'll get back to that and below the chapter list we have a P tag that's just going to that they can drag and drop to the chapters because we be adding that functionality as well so see drag and drop to reorder how can one man be so bad at spelling re the shaps all right let's just get some classes make this a little better looking class is text extra small text muted forr and margin top four and after the lse if would have now our else and then the else we can say P tag let's use div just doesn't signify anything so let's use a div and say no chapters give this class text SM Marin top to text slit 500 and italic save that and now let's create the shapter list components so you know the first thing to do is to create a new component called chapter list dot spell sfc and what we want to do here is install a dependency called spel DND action this will allow us create the drag and drop effect so open your terminal control J create a new terminal M has closed already so how I like to do it just separate both terminals here this one is run the application and this one is what I will use to install components and dependencies that I need now this is the package that we are going to be installing I'm in mpm yeah I will just click on this copy icon to copy it I can just copy like this and I'll paste this here and I'll just change this npm to pnpm and I'll click on enter here so that should install the package and as it installs the package I just want you to scroll down you see a section for typescript right here so set up is optional but we want type safety so we come to this F for part and just copy this so when you copy that go to your editor go to your app. d. CS4 and in here after you have this namespace app but still inside your declares Global just paste all of this code there so when you've pasted those there now you have typing for this Library so let's go back to our chapter list component in my script tag I want to create a variable to hold the flip Direction in milliseconds so I'll say flip duration Ms is equals to this will say 15 and can have a function this function will be called undo conid this consider and in the brackets just the E for event but it's going to be of type [Music] custom event and just say D and the event and there the event yeah would say it's going to be Shar and chapter would be from the types chapter that we have let me sure this chapters actually Imports and I Lally just remember one thing now when we imported the type of chapter here we just imported it as normal input but this is a type so I'll say import type like that and yeah that should go away so now yeah what I can do is say items and items would be a um uh prop so we say export let items and items will be a type shap T so we can say items would be equals to e do details as you can see we have typing and see details dot now we can say items and that's the function for the consider we will not another function for the finaly that's a function finaly finaly is going to basically be very similar to the consider with the typing and all that but in the finaly would remove this we just say for now I just want to D structure the item and I rename this to new item and this will be equal this will be from E do detail this items CU it's plural before we start building it out correct this spelling error now we don't need this div we need directly as a ul and this Ur would have an action so say use that's not where we put actions we put actions as attributes so see use and we use the DND [Music] Zone and DND zone is going to be from spel DND action and in here we can just put the options so I'll say items is items and you can see flip duration Ms and that basically all the ones that I need and after I can say on I say consider going to be I consider and yeah I'll say on finaly it's going to be off and do finaly let's just rename this and finaly as well I don't want to use finaly consider let's use and finaly after all that what we can now do is Loop through that items um array which is just going to be an array of chapters each block so do basically something like this but in this Li all right here animate and animate would be flip duration flip duration Ms like that and I'll put um a class I need to import this flip from spell SL animate so if you in Auto Imports you can write this by hand by keyboard then I say class I need the class I because I want to add conditional classes conditional Styles I use CN from the Le you my bracket right Flex it turn Center Gap X2 PG slit 200 border slit and that's not SP border again border slit 200 border and text slit 700 that's 799 700 rounded MD we also have a margin bottom of four and and text SM now the optional styles that we want to add is the comma and then craes and then we'll add this um BG Sky 200 B Sky 200 T Sky 700 if items that is publish is true that's basically what we're going to do and in the LI tag we W just have the title being displayed like that no would have a div and the div would have class and this class would be CRA CN cuz going to have conditional classes as well we put our brackets and and say PX that's padding left and right two we want put this in string format PX 2 py3 border R that's border right and say border R that's border right and then want to give this color so we can say um slit 200 I say over so that me you over this over I give a BG slate um let's go with 300 then we have rounded L that is left of MD then we have transition and we misspelled transition have another s transition now for the optional classes that we want to add this come after all those classes that we added call braises here I'll just say B right Sky 200 and over and basically copilot is correct this time over BG Sky 300 and then item is published so in the div itself now I can have um first of all I want to have an an icon agree icon say grip and grip will be got from Lucid so just allow that to a import for us um we don't have anyone with then just grip so let's go with grip icon it's the same thing and here I will give um grip icon classes class that I will give it is size five and outside of the div that is covering the grip icon I will have a P tag with class TR Kate in that P tag I have the item. title and outside tag I have another div this if we have class and in this class we have margin left Auto I want this to be at the extreme right now ping right two then now we have Flex item Center give this space this can be one one word like that say item Center and Gap X2 now have an if block here saying if I'm want to check if item is actually free if this item is free so remember uh as a teacher you can set some chapters for free preview so we can make this chapter free so you can say if item dot is free and I just put this if block isn't covered so let's close the if block so if item dot is free I want the badge and then the badge I'll just put free I make sure we import the badge so I just CN cni badge and also the um on that if block would have another badge and this badge is going to be showing whether this course is published or this course is branch and I also want to give this badge some Styles so when it's published it look a bit grayish and when it's I mean when it's published it looks a bit brighter than when it's dra when it's dra looks a bit dull a bit grayish I want to add conditional okay let's first say BG slate 500 and but if this is published want BG Sky 500 if it's published let's go 700 so a little bit brighter yeah and outside out um badge I would have an a tag what this a tag is going to do is just take me to um this chapters page this particular chapters page because of would have a page dedicated to Chapters put my craes in front here and I'm using the page store so I'll just page and this should be imported from me yeah exactly from App SL stores I'll P it the last sign in front of this to Auto subscribe to it so we say page. URL dot P name that's what we want and after that say slash shapter chapters slash another call braces open and close item do ID and in this div I mean in this a tag sorry we just have one icon and icon will be the pencil icon signifying that you can edit this chapter so we say pen and pencil icon from Lucid fa and yeah don't need all this transition that copil just popped let's just save this crol KS and see the way this looks like in our browser and an error I'm expecting an error and yeah internal error and the reason why we are getting this error is because of we are expecting in this chapters form the um data prop and in this chapter list that would import here we'll be expecting an item prop as well so I'll say shapter this like that's that's correct and I will get rid of the comment go to the page and in here expecting two props actually we're expecting the chapters and the data props I go back to my chapter form you see that right here I'm having exper for the data export L for the chapters now see underlines what underline me so we need to actually import this let's go back to our page first let's deal with the shapter prop so the shapter prop is basically going to be um chapters so chapters would be equals to the c. expand I want to expand the chapters collection and if there is no collection we just use an empty bracket and for the data we have to return a shapter title form from the server so I'll call this data will be equals to shapter title form and C okay so we use c letter T here now let's go to our server file so we can actually return this because right now we're not returning this just scroll up and the first thing we need to do is create a chapter schema so shapter title schema just go to your schema file and just after the price export const shapter title schema and this is going to be equal to Z do object and the only fi that would need here will be the ti and can say Z do string minimum is one and I remember that in my shapter form as well we're using the title scheme and not the chapters not yeah need to use the chapter title schema so everywhere we have title schema just contr d d d I'll change this to shapter T schema like that now I can go back to my server file and here I just duplicate this okay I can scroll back I don't know why I jumped down I must have pressed the key combination and I'll rename this to shapter title form and in here I put the [Music] Shar title schema and I make sure I import that and because I don't want any default value I'll get rid of this first arguments here this C spot but because this is going to be a duplicate form I want to give this an ID I'll say ID um chapter title form and the chapter title form I'll just return it the way I'm returning every other form in my return statements here now I'll control K and S to save every unsaved files and I'll check out how this looks like in the browser and now I'm in my browser and I'm seeing my C chapters and I'm seeing this components as you can see when I click on add a shapter we have this error and if I go back to the shapter form component back to that button that the button is simply supposed to toggle create create when we tle creates this form would come live and it's because of this form is coming live that that error is showing so let's look very well on why this error would show and simply