Next.js, Tailwind CSS, and MongoDB Project Tutorial – Ticketing App

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this comprehensive tutorial you will learn how to use nextjs the new app router and the power of Tailwind CSS to create a ticketing application from scratch you'll learn how to set up a mongodb atlas database and seamlessly connect it to your nextjs app using the mongus library in this step-by-step course Jake lower will help you master the art of building web applications with the latest Technologies what is up free code Camp thanks for the to the channel in today's video we're going to cover creating a ticketing app with nextjs new app router so this is 13.4 plus as of recording this video it's like 13.5 right now but anything should work we're going to cover all the crud applications and show you how to hook it up to a mongod DB Atlas instance for free as well as Tailwind CSS for our styling if you like these kind of videos don't be shy about checking out my channel as well Clarity coders we have a next off video coming out very shortly you can maybe find the link in the description or the comments below let's not waste any more time and jump right in so what we're going to do specifically today is work with nextjs and we're going to use the new 13.4 app router that's now stable to set up an application and you can see how quickly we can flesh out a front end and back end all in one application all at one time we're going to create this basic ticket app and we're going to do all of your crud functions so we're going to be able to create tickets update tickets delete tickets and read tickets into our application we're going to do this with as few libraries as possible and I'm not going to do a lot of fluff in this project because I want you to see how we can quickly spin us spin up this application then you can grow it over time let's not waste any more time and Jump Right In I'm not going to set up a lot of stuff in this video I'm going to assume you have no JS install but if you don't you're going to want to do that first so you're going to search for nodejs and you can download whatever the LTS version is right now so go ahead and download that and install it that's going to give you mpm an MPX that you can install your project with I'm also going to use Visual Studio code you don't have to you can use any text editor or IDE you want but this has a lot of unique libraries and features that I'm going to show showcase as well that make things really quick so now what I'm going to do is I'm going to use the integrated terminal as well so I'm going to open up a new terminal window and I'm going to actually create our project you can see here that I'm using get bash you can The Bash shell you can use whatever you want again you don't have to follow my but if you want to follow along and everything looked exact that's the terminal that I'm using as well down here so what we're going to do is we're going to navigate to wherever you want to create your folder so I'm just going to do it on my desktop here create next app we're going to use 13.43 cuz that's the version we're on right now so if you want to follow along exactly don't want any surprises that's what I do if you're relatively close in time to when this video is released to running this project you can also do at latest and that would probably be fine as well I'm going to do this just so it's for sure going to look exactly and work exactly like we're showing you here in this video now you can title your app you can't use capitals and this is going to actually create a project folder wherever you are so whatever we call this it's going to create that folder on our desktop so we can call it ticket app or whatever you want let's not use typescript so make sure the blue is on no we'll use eslint we'll use Tailwind CSS we don't want the source directory we want to use the app router and we do not need to customize so we're going to select no here any import aliases all right awesome so now it's created our app so now we should have that folder on our desktop so we can CD into that or whatever terminal you're using it might be different so we'll CD into ticket app cool now our terminal is there and we can actually open that folder in Visual Studio code as well so you can go file and then open folder and then navigate to that folder once you do that you should have something like this so this is going to be the basic of our project everything now is contained within this app folder here most of everything that we'll need so we got our page our layout and our Global CSS we'll look at that in a minute we are going to use Tailwind for this project so you'll see we have a tailwood configure that we're going to use and of course your package.json that you can see all the libraries that we're using as well I want to run through really quickly the extensions I use with my project because I do use them and it does help a lot so the extensions that we're going to use in this project or that you can use to help is this es7 plus react redex react native Snippets and it's by DS znj d r it has 9.2 million downloads what this is going to allow us to do is create boilerplate code really quickly I'll show you in a minute so if you want search for this extension in the marketplace and install it another one that we're going to use is eslint so if you search for that it's by Microsoft this is going to show us airs and linting in our project you'll see how that works as well go ahead and install it it's very helpful shows you problems before you know there's problems that kind of thing we're going to use prettier now this is something that I'm uh I don't know maybe it's maybe it's not the thing that I'm brow of but it formats your code automatically on Save it's so freaking handy so go ahead and if you want to install prettier as well so you can get a little sloppy when you're writing your code and then as you as soon as you hit contrl s it's going to save and format that code and make it look nice for you so I use that as well and the last one that I'm going to show that I use is Tailwind CSS intellisense so this is Tailwind labs and it again it gives you Snippets of code um but if you want to follow along exactly go ahead and install that as well with that being said we should have all of our extensions installed you can pause and do that if you would like we can open up our Global CSS shrink this down a little we're going to go ahead and delete everything out of here but one thing first if you're using prettier I want you to go ahead and hit fold control and shift and then hit P or whatever depending on your operating systems and then we're going to search for preferences and the open settings UI and from here we can search for formatter so you want to make sure a couple things are switched you want to make sure your default formatter is prettier and you also want to make sure it's check check to format on Save that's going to give you the functionality that you'll see on mine in a minute where when I hit contrl s to save it's going to automatically format my code so let's go ahead and we can do a little bit of cleanup here actually if you want to we can open our terminal and actually run our project and see what it looks like so in our terminal we can open it up make sure you're in the folder we can do mpm runev should give you a URL here we can visit that you can also just type this into your browser we're going to Local Host 3000 if you're on the default port and nothing else is running on it that's what should show up and here you can see our application has been created and it's running we're going to chop this down and start a little fresher so let's go ahead and cut out all of this in the global CSS we can hit contrl s to save let's go to our main page here so this is kind of the first uniqueness of nextjs so you'll see that we have a page.js this is almost like an index.html and like old school HTML projects where it's the default page that gets displayed so this is a PL page that's going to get displayed when we open up our app let's go ahead and cut this down a little bit so everything inside the [Music] return I'm going to delete now we just have this set up actually we can delete everything if you want and I'll show you how we use the other snippet Library so the cool es7 snippet library for react you can do RAF C and that's going to give you a default page if you hit control shift L we can edit all these at once and we can call this our dashboard delete out that top react line we can save this and now we have our default dashboard set up now to make routings super quick and easy inside of nextjs this app router we can navigate by creating new folders so let's create a new fault folder and we'll call it ticket page and inside of here we can create a new file and let's call this page. jsx we can rename this and make it jsx as well so here let's do the same thing let's do r a c control shift L we can call this our ticket page lead out this top and we'll save so now what nextjs 13.4 is going to do for us it's going to create routing to this page automatically based on our folder structure so you'll see that we called it ticket page here so if we go to our application you can see it's automatically updated we got this plane Jane dashboard page now we can actually navigate out of the box without any other code to that ticket page and now you'll see we're on our ticket page we created we can do something else as well let's create another folder now this is inside the ticket page folder we're going to use square brackets and we're going to call this ID so it's open square bracket ID close square bracket let's put this page inside that folder so let's move that so now it's inside that ID folder so make sure it's set up like that and now we can do something pretty cool here so we can destructure Rams and then we can use that variable that ID variable that's going to be in our URL and I'll show you how we're going to do that so we will inside of here here we can do dollar sign like that now this ticket page doesn't exist anymore because we move that page so let's do slash and then we can type in a fake ticket ID like this and you'll see that it spits out that variable to us we actually don't have to use the dollar sign I don't know why I was confusing myself so we can do it just like that and it'll spit out our variable so this is pretty useful we can grab off that with our pages and this is going to allow us to create this app with basically one page here so that's going to be our basic setup so you might be asking yourself what if I need a folder but I don't want routing to be set up to it well we're going to use that in this project as well so if you right click on app and create a new folder you're going to do open parentheses and then create your folder name so we'll call our components we're going to actually use this in the project and hit enter now because it's inside parentheses it won't set up a router for this so users I mean they can type in slash components but it won't navigate to anyway so we can write click on this and then for example inside of here we can set up our navigation because that's going to go on every page so we can create nav.no rafc and then we've created our nav page and it's as simple as that now this isn't going to be no one's going to navigate to this or anything like this this is just a component we're going to use in our project that's the basic of the routing we're also going to have an API folder that allows us to access our back end but this will at least get us started here so let's go ahead and jump into our layout page now this layout page is pretty straightforward the only thing that's kind of unique unque about nextjs is you're going to be able as you can see here to use Google fonts directly so you'll see the default project already uses a g Google font sets it up here and then passes it in so that's all set up nicely for us you can see there's some metadata that you can set up so we can call this our ticket app and change it to generated by Clarity coders something like that and we got us all set up here now if we want to pull something into this page so if we want to pull a component in it works exactly like you would think so if for example we wanted to add our navigation to every page right now it's displaying the children so the children are going to be the pages that we're passing in so if we wanted for example our navigation to show up on every page we could do nav and now using intellisense you can tab here and it's going to do the import for you so I'm going to tab you'll see nav gets imported above then we can do slash and then close that now make sure you have the nav if it didn't do it automatically you got to type that in take a look now you can see our navigation is going to show up on every page of our project which is what we would want now you can see our navigation there as well so with that being said let's start setting up the basics of the front end of our project so we're going to get it kind of looking like what we want to look like here now I said we're not going to use a lot of libraries but I am going to kill that terminal and we'll do just a couple Library installs here so we don't have to use images or anything like that in this project we're going to use a free icon Library so let's do mpm install and let's do at bort ft awesome slf free- solid dsv g- icons space and we're going to do one more we're going to do at Port awesome SL react D font awesome tell me in the comments I don't know why it's Fort awesome at the start of this instead of font that doesn't make a lot of sense to me but that's how it is so type it in exactly as I have here hit enter and it will install those libraries we'll wait for that to finish there we go nice and quick and then we can finish up our layout page here and our navigation page so one thing that's kind of neat about Tailwind CSS is we can set up our default colors in this Tailwind config.js so let's go ahead and knock that out out of the box here and what this is going to allow us to do it's going to use standard eyes color names that we can create and then if we want to change things later in our project we can change it in one spot and it'll push it throughout the project wherever we use that previous color so right after background image we can create a colors block here and inside that we can define define colors however we want so for our navigation let's just call it nav we're going to pass in a color now I just checked out these colors and kind of made something that I thought looks sort of acceptable I am not a designer by any means so pick out any color you want but this is the color that we're going to use for our navigation then let's do page and we'll enter that as well to B3 441 this is going to be the background for our page the background for our cards will be 475 66a we're going to create a card hover color so this is just when when you hover over that card itself it's going to change to a little Lighter Shade that's going to be 4 F5 E74 we're going to have our default text color for our entire project is going to be just an off white so it's going to be F1 F3 F5 just a couple more here pretty simple project so we don't have a whole lot we're going to do a blue accent color this is going to be the button on our form when we create a ticket 0084 D4 and then let's also do a blue accent hover color this is going to be 009 F FF save it so now we got all of our colors set up for our whole project it's going to be nice in this Tailwind config file I think that's everything we're going to use with this file as well so let's go ahead and shut that down and then inside our layout JS we have a couple unique things that we have to do with this project for our icons that we're going to use this is really quick but essentially when you're loading in these icons sometimes they show up really huge so we got to change and then they um Define back down so it's kind of weird it makes it look jumpy so we're going to do a quick fix for that so we're going to import config and this is going to be from at for awesome slash and now we want to use the port awesome SVG core so if you got it in intellisense you can put it in there and that'll get you your config file and then we also want to import at Port awesome SL font F awesom SVG core styles.css now after this we need to add one line I think just one line config do auto add CSS equals false so now it's not going to sub in CSS automatically for us and that's going to help with that jumping of the icon so we shouldn't have to deal with that in our project we're going to change our page setup just a little bit here so it defaults a little nicer when it when everything shows up so we're going to keep the body tag there but we're going to add another div now we want this navigation to span the entire top it's like a top bar on a website so we want it to span the entire top of this project so using Tailwind we can use class name and set it equal to and then we can type our Tailwind commands directly in here so we're going to use flex for the layout we're going to use flex column so that's going to show everything on top of each other so our navigation is going to be on top and then our ticket page so on and so forth if you want a sidebar you wouldn't use flex column you you'd leave that out we're going to do H screen which gives us the full width of the screen and if you hover over this or the full height of the viewport so if you hover over this you can see the exact CSS it's adding and then we'll also make it a Max screen so we're going to give a Max screen size of that full uh viewport as well that should be it there these are pretty simplistic again I'm not a designer by any means and I want to keep this as simple as possible so let's surround the children with another div so you can see here how I kind of have that set up let's add a another class name here we're going to use flex grow this is going to expand the main page to fill up the whole page we're going to do overflow y Auto and now we're going to set up the color of our page as well now if you remember we set up a variable called page but with Tailwind CSS we have to tell it what we want to use that color on first we want to use it on the background we're going to do BG Dash now you can see all the default colors that show up but we're going to use our custom one of BG page and you can see our intellisense shows a nice preview of the color and everything like that so that is going to be our background for our page and we're going to use our text so this is the color text and now we can use anything we want here but we want to use our default and you can see intellisense popping up default text so this is going to be our default text color now we can save this contrl s and we should be good now if we look at our project well we got to spin it up again so mpm run Dev in your terminal see that's working let's refresh this and cool you can see our Tailwind CSS has worked you can see our navigation is along the top now we haven't done anything with that we'll do that next but you can see it's at least in the right spot you can see our dashboard below has the right page color on it making progress so let's jump into our navigation and get that structured out as well let's go ahead and delete everything inside this return we're going to use a nav tags like this and then we're going to use a div inside of that and there are going to be two icons in here and then we're going to do a second set of divs below and this can just be our placeholder for a login system later now we're not going to do that in this project but I have an advanced video that you can check out that will go over that as well that I'll be releasing soon this is not my email so don't email it I don't know who that is so this will put a fake email just a placeholder in our navigation and over here is where we're going to want to use our links and our icons for our project so here we can use the link that's built into nextjs so you'll see here it says next SL link let's go ahead and tab it'll add it up here make sure yours is using nextlink that'll give us links there we have to add an href to this so we'll add an hre this is where we're going to link so this one can just go to our homepage so we'll just do slash and then inside of here let's use one of our font awesome icon so as we start typing in Tel ense is going to help me out font awesome icon and you can see it does the import up here make sure yours does that as well and then we're going to add in a specific icon now you can search font awesome and you can find all the icons available to you I've already found them just to be just to move the project along we're going to use f a ticket so I'm going to tab here again and telesense will do the import For Me Above fa ticket and we're going to give this a class name and here we're wanting to Define how our icons will show up but we're going to use this over and over and over again right in our project and I don't want to type this out every time so we can create our own class name so we'll call our class icon and then we can reuse that in other spots so we'll Define that in our Global CSS here in just a moment let's copy that entire section there and we'll make a new one here we'll call this our ticket page Slash new lowercase and I'll show you how that works in a minute so here we don't want the fa ticket icon let's do yeah we do let's use fa ticket here actually for this one let's use f fa home so now you can see you should have two Imports you should have an fa home and an fa ticket from font awesome and you'll see that it's got everything set up that's good but we haven't defined this icon class yet so let's go to Global CSS and in here we can set up a lot of our basic rules now I'm not going to get into all these but Tailwind is set up with base components and utilities and things can overwrite other properties depending on which you're using so for us we're going to add to the layer components and here we're going to Define two classes to start out with let's define our icon first and then we'll do add apply and then we can add whatever we want to the icon class so we want it to be a color of text default and we want the text to be extra large now we're going to do another one here that we'll use later to Define our button so let's dot button and here we can do a hover of no underline actually want to do at apply so one thing that's cool about Tailwind is we can Define things certain properties like this for certain tasks so again we we only want it to remove no underline when people are hovering over it so it makes sense sense to put that there we want our B our background so we're going to do BG Dash blue dash accent and we want the hover color so let's do hover again to be BG Das blue- accent Das hover so now we have no underline our background color our hover set up that all looks good we want to do tracking wider and you can see what that does so if you hover over it it's about letter spacing this is the longest line I think just in terms of what we add to our CSS so we're going to do w- full we want the text to be centered we want the text color to be the same as our nav bar so we'll do text dnav we'll do font Das bold we need a cursor that's a pointer I'm going to use the intellisense let's make everything uppercase we're going to do a padding on our x axis of four so this going to do padding left and right and four is not four pixels if you hover over it it's actually 16 pixels a py of we'll do rounded so this is our border radius is going to be rounded we'll transition our colors and one more here we'll make sure it displays block so that's it I know I'm throwing just a lot of stuff at you right there but basically we're just defining what our button will look like you can use any CSS for any button that you would like but we'll get that out of the way now since we're in this file so we got our icon set up we got our button set up make sure you save this and then we can go back to nav we're not going to use the button in the navigation but it's ready for us now so we got our icons everything looks good there we go back you'll see yeah that looks you can start to see it there it's the wrong colors and the and the setup isn't great but at least we're showing up so let's add a tiny bit of structure here so we'll say class name again we're going to use flex now this time we don't want to use flex column right because we're not we want the icons and the and the email address horizontally spread on the page here so we'll do justify between that's going to space everything equally between we want our background to be our navigation color so we'll do BD BG dnav and we want our padding to be four again I played around with these these you can uh I'm certainly not a designer you can you can use whatever you want there class name for our next div is going to be Flex We want our item centered these are going to be our icons and we want a space X4 now what you'll see here is it's doing some mathematics to get our margins so they can be spaced equally between so it just makes those icons look a little nicer and I think that's the basics of what we need so if we look back everything looks pretty good right we got two buttons or two icons here we got our email this is kind of a placeholder right now and then we can navigate around so if we click on the new ticket you'll see it pulls us to the new page and you'll see that it's still pulling that ID down remember this is the ID variable that we're passing to that page now if we go home we're back on our dashboard and that's pretty much the entire setup of our application it's pretty simplistic so we're ready to rock and roll there awesome we should be good so we want a to add a bunch of components here so let's create a new file inside of components and the first one we're going to create is our delete block. jsx we can do our normal rafc that'll give us our boiler plate cut that out and now for our delete block as you can see we're just going to use like a red X so we can go ahead and add that into our project just to get it set up and working it's not going to do anything at the moment so we will just create the icon so let's do font awesome icon like we did before hate how it did the import I don't know why it did it like that let's do import font awesome icon there like that better this will have to have a slash at the end see I just fall apart when my intellisense doesn't work let's do icon equals now I already picked out an icon so we're going to do fa capital x so this is literally just the x that you see the icon that you see and then we can set up some class names here as well so let's do text of r r- 400 is going to be the color of the text itself when we hover I want the cursor to change to a pointer so it looks like it can be clicked on and I want to set the hover color to be text- r-200 so this is just going to be a lighter version of that and that's the basic of our delete block let's create a new component and this is just so you can see how we can kind of put this all together let's call this ticket card. jsx RFC see here we got our ticket card here we can start pulling in our different items so for example we can pull in our delete block here you'll see it's importing our delete block slash like that you'll see now our ticket card shows up with the delete block now if we go to our project nothing's going to show up yet right because we're not using that ticket card anywhere and we're not using that delete block anywhere yet so then back in our dashboard page here here's where we can add in our ticket card that's again a component that we're going to import you can see now we got our ticket card so now if we go into our project you'll see our ticket card is just a red X right now but but you'll see it does at least show up so you can see how we're kind of using components to pull everything together here now these are components because we want to be able to reuse them right eventually in our project we're going to have multiple ticket cards now this obviously isn't going to look right at the moment um but you'll see we're able to use reuse that code without retyping it or anything like that all right so the other parts of our ticket so we have our delete block we need our priority display so let's create a new file we'll call it PRI ority spelling is tough for me sometimes RAF CE get our boiler plate there now for this it's kind of cool we have the the five like fire icons and depending on how hot this project is no pun intended is how many are filled up with the with the project so we're not going to set any of that up quite yet but we do want to add in our icons so let's add in five of those icons let's say font awesome icon imported better this time so I like that and for this we're going to do a icon that [Music] equals fa fire you'll see we did the Auto Import there as well let's get five of these so there's one 2 3 4 five now prettier watch this magic contrl s boom we're getting somewhere for our class name oh I should have done this first huh we can do text- R d400 just for now so these are all going to be hot at the moment we can copy that I should have done this first paste it below Okay cool so we got our five icons here now just a little bit of styling we want these to show up horizontally so we'll do Flex we'll put them all at the start so we'll do justify start and we want to align them to the Baseline of whatever the container is and then they'll all show up that looks good these are going to go in our ticket card as well now these are not set up correctly but we can at least throw it in here so we'll do our priority display take a look at that look at that stuff is showing up in our ticket cards automatically okay so let's go ahead and rifle through the rest of these we got our priority display we wanted a progress bar as well RFC delete this one out this progress bar is pretty cool we use two divs essentially to set up an outside div that's like the unfilled part of the bar and then the inside div which based on a percentage is going to fill up the progress uh bar that we see so we'll use a class name for this top div we'll say we want it to be width full BG Gray 200 that's going to be the background color rounded full so this is the Border radius so it's going to give it that rounded look we don't want round we want rounded this is just the height so we're going to give it a height of 2.5 and then our internal bar so this is going to be the internal bar that fills up we can use BG blue 600 as our color again you can play around with these the same height of 2.5 and we want it to be rounded D4 now we're also going to use the style variable here so we'll use style and this is going to be to get our percentage to show up correctly so we're going to do style equals in double curly brackets we're going to do a width of 75% right now so we're just hard coding in these values we're going to pass Dynamic values in a minute but this is you can kind of do it however you like or however you like to set up projects but I like to kind of get a look or feel without using the database data to make sure everything works and then add the rest of that in as we progress but this should be good here back in our ticket card we can do progress display cool this one one probably won't show up right because yeah it's just going to fill up everything at the moment we'll get that adjusted in a second it would help if I spelled width right as well width of 75 now you'll see it it shows up okay it's not formatted correctly but you get the idea our next component we need a status so we want to do started done or not started you can do whatever statuses you want as as well but inside here we're going to do a status display do jsx you know how to do this RAF CE let's use a span for this so we're going to use span tags and inside here we're going to do some formatting to get kind of that rounded look so we're going to use inline block rounded P you guys are probably going to be like you round too many of your Corners I I'm not a good designer like I said so if anyone wants to help me out join the join the Discord let me know you'll help me style my next project so we'll do to text extra small font semi bold text- gray d700 and then we're going to hard code a in here so depending on the status it's going to be color different but for right now we can do the done color which is going to be BG D green D200 and then of course we're actually going to have the status in here so something like that for now is fine um because we're using the green color but eventually this will be dynamic then in our ticket card we can add in this status display as well awesome yeah I think that looks pretty good let's go ahead and maybe format up our ticket card a little bit so it looks a little more like our end project so we are going to have an outside div around everything so let's leave that and let's set up our class for this so it's going to be Flex we're going to build it vertically so I'm going to use flex column the background color we're going to use so BG card we're going to do a hover on this because you can click on them of BG card- hover remember we set that up before we're going to do rounded a medium because you guys know I love rounding those Corners shadow of large just to give it a little drop shadow padding of three and a margin of two now on top we have our priority display and our delete block I just have these in the wrong order so let's put our priority display on top now these are going to have a div that wraps around them so let's put a div around the priority display and the delete block here let's add some classes to it so there going to be spread out along the top as you can see here we'll set up our class name we'll set it equal to flex margin bottom of three just to give it some spacing below this going to wrap around everything now we're going to use one more div around the delete block this is going to slide it clear to the right so let's wrap another div around the delete block we can do a class name of ml l- Auto so this is going to automatically give us the correct amount of margin on the left to slide it over so we can slide it clear over to the right we save this you can see our Bottom's still messed up but our top is looking better now the next thing I want to do is I want to set the H4 tag and this is going to be the ticket title and below that we can do a horizontal row let's do a class name of hpx let's do a border of zero let's make the background our page and a margin bottom of two do slash and then close that so these are the self- closing tags let's do a p here for our description of our ticket let's do a class name of wh space Dash free- wrap so what this is going to do is it's going to save the returns that we make in our ticket so if we do like a paragraph and then a couple returns and then type some more in our ticket description that's going to show up okay so that's good enough for our ticket right now if we look we'll see yep we're getting closer now you might wonder why does your H4 look exactly like the P tag well remember we deleted out all of our Styles so those aren't styled at the moment so if we want to fix that we could go back into Global CSS and we could set up some of those default Styles so the one thing we want to do here is we can and create an at layer base for our H1 comma we'll do H2 H3 and H4 um these are the ones that we're going to use in this project we can do at apply font Das bold so this is going to give every one of these bold font and then for the individual sizes we can do H1 we can do at apply x-4x LL for example let's copy that we'll do H2 H3 and H4 we're can do an H2 H3 H4 for this one we can do 3 XL 2 XL and XL right now for our P tag let's do at apply text- smm and let's do text- default text make sure it's colored correctly as well so now we should have everything done there if we go back you can see our ticket title is better and our P tag is formatted as well so that all looks fine now we can go back to our ticket card out of some of these I've gotten a little messy go back to our ticket card let's continue formatting this so below our paragraph This one you're going to have to trust me for the moment we're going to do a flex Das grow empty div so what this is going to do is it's going to make sure that all the ticket cards are the same size regardless of how much font they have inside of them just a preference thing if you don't like this you can remove it but I like I think it looks good with them all being the same size we'll do another div here now this is going to wrap around our progress and our status display so start the div there end it here let's do class name for this one we want to do Flex let's do a margin top of two that will look good and then the progress display we're going to put a div around that because we're also going to add the date time that the ticket was created so let's say class name here let's do flex and flex column then inside here again all placeholder at the moment but we're going to do a P tag of our date time 0831 SL 23 at 10:43 p.m. that looks good let's get that formatted to while we're at it this one's going to be on the left side so let's do this of a text XS so a text of extra small and a margin y of one that should be good and then for our status display this is the one we want to scoot over so for our status display let's give this a class name of margin left Das Auto Flex items dend div div okay so now we should have a basic structure here cool so you see we got our ticket our progress bar our status our time everything is kind of looking good the hover works all that is fine you'll notice though that the tickets are taking up the whole page we want to get that fixed but it looks okay for the moment let's jump back to our code our ticket card is looking good let's go back to our page now remember this is going to be our main dashboard page of this project so this is where all of our tickets are going to display let's do some basic Styles in here inside of this div let's do a class name of p-5 and this probably has the coolest part for me of Tailwind uh that you'll see here in a moment and then we're going to use another div around the ticket so we'll do div class name now we can do some styling here based on screen size so that's what I was talking about that's really cool so on our smallest screen we're going to have the tickets take up 100% of the space like they are now if you're on a phone or something like that however on this huge monitor that I have I don't want it to show up like that so I'm going to say if the screen is large so at least a large screen and you can see how this is defined and you can actually change the definition as well but we're going to use the default ones so if we have a large screen we're going to set it up with a grid and we're going to do grid calls 2 so there's going to be two columns however if it's an extra large screen we want to do grid C-4 so if it's kind of a if it's a large screen we're going to use two columns if it's a big screen we're going to use four columns and again this is I mean you can change that to be whatever you would like as well so we're going to wrap this div around all of our cards let's actually create four cards since that's the largest that our screen will be and you can see now it looks kind of nice right so now we have our four tickets spread out because we're on an extra large screen now if I minimize this window or Shrink it up you can see right there that it auto adjusts this is what like a phone would look like and if I slowly drag over you can see this is where it decides it's a large enough screen to have two tickets and this is where it's large enough to have four tickets now why did I have it jump from two to four just preference again you can make it three or whatever you wanted to do do but that's how that's what I thought looked the best so that's going to be our basic setup there so now we have kind of the the basic structure of our app we have the routing setup we have the ticket set up we have our main display the thing we want to do next is to start looking at setting up our database so we're going to use mongodb ATL lless this is a free free to set up so you shouldn't have any issues there and I'm going to kind of walk you through that process as well if it's new to you I'm also going to use so what lets us do is in mongod DB we don't Define types like you do in a traditional relational database so you don't say that the title has to be a string and that the priority is one through five like a number you can't Define things like that but Mongoose allows us to have that data Integrity so I really like that as well and it also actually kind of makes setting up and connecting to the database a little bit easier so let's go ahead and kill our server this is just so we don't forget here or so I don't forget let's go ahead and add in those two packages and this might be it for us too in terms of packages so let's mpm let's do mongod DB and then let's also do space ah you need to do mpm in install space and then those two libraries so this is going to give us the packages that we need here that should be all set up now we can actually create our mongod DB so you can search for mongod DB Atlas maybe mongod DB Atlas we'll click on that first link go ahead and sign in now I'm going to skip through this part but you can sign in you can use your um Gmail or you can create a new account whatever ever you want to do you can do it for free so go ahead and sign in and sign up now once you've signed in you'll accept the privacy policy or whatever you need to do there it might ask you some questions I'll buzz through that when it gets to this screen we can go ahead and fill this out because we are going to use it so if you already have one set up you can uh we can even hit I'll deploy my database later so you you should look at this screen no matter what you might have came to that preview one or if you already have signed up before you might come to something that looks like this but at any rate we need to create a database cluster so what we're going to use is the m0 which is the free version you see it's running on AWS it has a name everything like that we can leave all that defaulted let's go ahead and hit create we're going to need a username and password eventually so you're going to want to set that up I'm going to go ahead and change mine to admin you can leave that password as it is as well um but we do want to save it so let's go back in our code and just as a placeholder for right here inside the ticket app itself not inside the app folder let's create actually click anywhere in this blank space a new file and let's call it env. local this is a special file that nextjs is going to pull in for our environment variable now paste your password in there and maybe paste your username as well above it as a placeholder for right now so we'll go ahead and create that user where would you like to connect from so you can add your current IP address here it's already been added um we might actually do a change this as well just to eliminate any problems but we can go ahead and finish and close for now and go to overview that looks pretty good if you want to open this wide open for right now just so you don't have any problems you can go to network access down here now I don't recommend you do this for every project but we can add another IP address and we can allow access from anywhere confirm so now we're going to have no problem connecting to it now click on database and we're going to go back here it's probably still deploying our database at the moment once it's done uh we don't want to add a tag I'm just going to hit okay there um once it's done you'll see cluster zero it has a little green thing next to it you can think of a cluster as a collection of databases we're not going to have multiple databases we're just going to have this one then we can go to browse collections now here we can go to add my own data we can enter a database name and then we can also add a collection name wow so in ours for example we could call it ticket DB and our collection let's call it tickets plural hit create so that should be good now we could add fake data here we could go back and create it and kind of import it what I'm going to do is we're going to leave this set up as is we're going to go back and connect to our database and then create the model of our data so what our data is going to look like and then we'll just start adding data into this database and see if we can get that working so let's go back to overview here go to connect we're going to hit this top one nodejs go drivers and then here you'll see our connect string here that we can steal so let's copy that go back to our code and in our code let's actually create our connection variable so let's go mongod dbor urri equals and then we can paste in this little snippet here now if you have a different username you need to change this username mine was admin so I'm not going to change mine and then your password obviously you're going to use your password I'm not going to leave mine running so I'm going to delete that out and then you can delete this stuff below let's also cut off this end here so I'm just going to do to the Slash and I'm going to do ticket DB or whatever you called yours database so again you got to use your information here um but if we go back to collections you can see what you called your database as well so I called mine ticket DB awesome now for ours it's relatively simple we only have one model we're just going to use a ticket for right now so let's do a new folder let's put this in parenthesis because we don't want to route to it or anything like that and let's call it models and inside here we can create a new file we can call it ticket. JS capital T ticket. JS in this file we need to import a couple libraries so let's import mongus from mongus do comma and then Capital this is important capital s c h m for schema this is going to give us mongus and the schema that we need we're going to do mongus doc connect to connect to our database we're going to use our variable that we just set up so process. env. DB DB uncore URI brain locked up couldn't remember what I called the variable so make sure this is the variable that we set up in the mv. local we're going to get a promise we're going to use our global. promise here and now we can Define what a ticket is so here we can create our ticket schema and this is going to be what sets up our data Integrity as well we can count on a ticket being created a certain way so it's going to have a title which is a string going to have a description which is a string going to have a category which is a string it's going to have a priority which is going to be a number going to have progress which is a number Status which is a string we might even want like an active flag something like that that's a booing so like a true or false that's later if we wanted to have like an archive functionality or whatever it might be now we're going to do comma and we're also going to add timestamps true so the time stamps true that's going to give us a created at and an updated at date so it's just going to be helpful to our project to have that in it as well so now that we have that we can create a con ticket and and set it equal to mongus do models make sure that's plural. ticket or so that's going to be if it exists already so if it exists already we're going to grab grab it or we're going to create it if it doesn't exist we'll do ticket ticket schema like that export default ticket that's it pretty easy and that's all we need to do to get our database hooked up connected and all that jazz now we can go ahead and start creating our API so as you might guess we're going to use the app folder again we're going to create a new folder and we're going to call it API so this is going to be how our application is going to act access our database we're going to create a new file inside of this and this is called route.jpg post delete whatever we might need we are going to use our model so let's do import ticket now look it's models it's going to import it from our folder All That Jazz that looks good and then this one's important because it's a little weird let's use next response and make sure this comes from next server and now we can create our first function so the first thing we want to do with our database in particular we don't have any tickets in it um typically you might fill it with dummy data or whatever you want to do I'm just going to create something to help us add tickets and then we can test it that way so let's do export async function post and let's pass in requests so we're going to do it just like that and in here we can Define our post request so posts are going to be how we create tickets we can do all these inside of a try catch just to make sure we don't have an error if we do have an error let's go ahead and Define that first we can return that response so let's return next response Json inside of here we'll say we want to pass a message back and that is error and then we also want to pass back our error as well we can do a comma after this curly bracket and pass a status code as well if we would like of 500 because it failed okay so that's going to be our error and this is actually you'll see how super easy this is so to create a ticket we're going to to get a request and that request is going to have ticket data on it so we're going to create a form that allows people to add data and they're going to attach it to the request and then we're going to pass it to the ticket and we'll create that next so you'll be able to see it so we're going to create a const for our body and we're going to set it equal to and we're going to await whatever was on requ request. Json so we're going to grab off the body data and using that ticket data this is the variable that we're going to call it we'll call it form data we haven't created it yet we will we'll call it form data we'll assign it to ticket data and then we're just going to create the ticket so we're going to wait ticket. create this is a mongoose function we're going to pass in our ticket data and that's it then it'll then it will create the ticket for us now we also probably want to create a response as well so we'll do return next response the message that we want is no longer an error so we want this to be ticket created we can delete out this error and we can pass a status back of 2011 which I think is object created or successfully created or whatever so this this is all of our post function now again we don't have any way in our UI in the like user interface now to get that data and create the ticket but this is the backend setup for it so with that being said let's go ahead and create our form that's going to allow us to create tickets so let's open up components let's create a new file and inside of here we can do edit ticket form jsx actually we can simplify that let's just call it ticket form. jsx RF CE we're going to do a couple Imports in here and I want to make sure we get them right so let's go ahead and do those let's do import use router now this is the weird one so if you do the default one it's next router and that's not what we want so we want next slash navigation and then below that we want to use import react use state from react now one other thing that we want to do here so we're going to in these next projects they're using serers side JavaScript by default but sometimes we want to use the client side JavaScript so in this case we want to use client side JavaScript because we're going to use forms and have actions based on it and different things like this so at the top we have to explicitly state that we want to use the client JavaScript so we're going to do that so we're going to use client now for our ticket form this is pretty simple we're going to set up our ticket and we need some default data out of the box so our starting data for our ticket is going to be starting ticket data like this we can set it equal to let's give it a title of blank a description of blank a priority of blank oh don't forget your call in there a priority not a blank a priority of one a progress of zero a status of not started and a category Hardware problem these are my categories so you can do whatever you would like so this is going to be our starting ticket data and then we're going to use that to set our state so this is going to be a state managed form so every time they change something we're going to update the state and keep track of that so we can pass that data eventually onto our API to create the ticket so let's use const form data remember that's a variable we used in the API eventually and we'll call set form data we'll set that equal to use State and then we're going to pass in the default state so the starting State here and the starting State we divined above in the starting ticket data so this is going to give us the setup for our state out of the box now we want to return our form so we're going to have a form here something like that we're going to have a div let's do some basic styling here let's do a class name of flex justify Center I'll just Center our form and then inside of our form we can start getting things set up let's have an H3 and this will just say create your ticket this is also going to be our update ticket ticket page eventually so that's going to be dynamic here in a moment but for right now we'll leave it like that as our H3 we'll do our first label of title and then let's do our first input box as well and then we'll do some quick styling here so let's do input let's do ID equals title name equals title type equals text on change equals we don't have this yet curly brackets let's do handle change let's make this required so required equals true and the value equals form data. title then we'll do slash self- closing here now you see that auto formatted everything for me nice and pretty now we don't have a handle change that's an issue let's go ahead and set that up real quick let's define it up here we'll do const handle change it's going to get an event we'll pass that in we're going to get the value that we want to change from e. Target do value like that and then we're going to get the name of what we want to update from e target. name now we need to set our form data remember we're going to use this state function that we defined do set form data we're going to pass in our previous state so we're going to first use everything from our previous state now make sure you spell this the same I spelled it differently we're going use everything from the previous state and then we're just going to overwrite the one thing that we wanted to change so we're going to do name and set that equal to value and I'm getting these from above here I need another parentheses here so it gets [Music] returned and that means another parentheses here there we go so this is going to update our state with our handle change let's go ahead and spin this application up again we got some issues here but we'll talk about it real quick should be easy to fix go back to our application we can refresh it now remember if we click on the new ticket we're not loading in the form yet so nothing nothing happens when we navigate to here we need to do that first so on that ticket page inside the ticket page folder inside the square bracket ID we have the ticket page right now we're returning this instead let's Import in our ticket form like that and now when we go to that page you can see we have our nice ticket form here now it's not styled very well but we can take care of that really quick too so I got some very very quick basic styling here we're going to style our form we're going to do at apply now why am I doing it in global CSS well if this is a real project if this is something that you're going to grow and we might even continue to grow on this channel you want to be able to reuse this right so I want to set up the styling for our forms so for the most part if we want to do another form it's ready to use out of the box so so labels will do margin top of four and then for our input comma select comma text area we will do at apply margin of one rounded because you know I love those rounded corners and a BG of card padding of one that should be it I don't want to get too crazy with the styling you're probably going to make it your own anyway so you see we got a little nicer format there I like that let's go back to our form so now we're back on our ticket form page I apologize for all the tabs open this is actually how I code too with all these tabs open so go back to our ticket form let's get the rest of this fleshed out and then we can start adding tickets to our database so on our form let's go ahead and add a few styles to this as well now why aren't these in the in the global CSS they they could be you know they're they're kind of specific so you might not use these on every form you use so that's kind of where I draw that line but it's totally up to you these could go in the in the overall form as well so we'll add a method as well so we want to post our data and then on submit we want to create another function called handle submit and we'll use that now if we save this it's going to freak out because we don't have that yet so up here we can do const handle submit submit equals something like that this might be the farthest I've ever gotten coding without using a console.log but we'll just have submitted for right now as we create our form out here so we should be good everything should be created now let's copy all of this so we're going to copy the label and the input paste it below let's call call this description description paste paste that all looks good the type is going to be different well actually the the input is not an input it's a text area that we're doing this time so we don't need the type we got the ID the name the onchange we're still saying it's required the value is correct we can make the rows however many we want we can set rows equal to five that should be fine now let's take a quick peek at this just because now we have our form um the class flex and all that jazz so now you can see it starting to look a little nicer so that's our description let's do our categories now you can dynamically populate these eventually you can hard code them for right now we're going to hard code our categories we'll do another label inside of here we can call this category we're going to use a select and inside that select we're going to give it a name which is category a value which is form data. category an on change of handle change so we we coded that up dynamically so we can use the same for everyone here that's going to be our select now we just need our options so for our option we're going to have a value which is equal to now for example what do we say our default was Hardware problem we can have a value of Hardware problem and we can show Hardware problem here let's copy this let's just give another maybe three categories do software problem and let's do project make sure the values changed as well sometimes these are different so you might want something displayed differently to your user um than the actual value so that's why you have two options there look at this you'll see our drop down is nice that works after this let's do our label for our priority we're going to do a div around all these so they show up in a horizontal line we'll do input we'll do an ID that equals Priority One a name which equals priority a type which is Radio on change which is handle change a value which in this case equals one just save so that would format and then below the value let's do checked equals let's look at our form data so this is going to decide whether which one should be checked at the moment so if our priority equals one so I'm using two equal signs here I'm using two equal signs for a specific reason I want it to not care about the type so I want it to check it if it if one equals the number one and I also want it to check if one equals a string one so that's why I'm using two equal signs as opposed to three there so that all looks good and then we just need a label below that and I'll show you why here in a minute of one that all looks good let's copy that paste it below now starting with this we're going to go two two for the value two for the comparison and two for the label this will be our three four five let's slide up here's the last two so here we're going to do our one is going to be changed to a three three three three four four four four five five five five cool so now we should have all of our priorities done let's go ahead before we look at it let's just do another one here let's do label for our progress now I did this progress bar because I wanted another type in here I don't know if you'd use this in a ticket situation I guess it could be kind of useful but um it allows us to show another thing here so type equals range ID equals progress name equals progress value equals form data. progress let's do our Min equals zero do our Max equals 100 so it's going to be a progress bar from one to 100 I save this just so it would format below Max we're going to do on change equals you guessed it handle change that should be good this might be our last one nope we don't want a stat not status tags let's do label of status and this kind of like our other one we're going to use a select box inside the select box we have a name of status we have a value equal to form data. status have an on change handle change and then we have some options so first option has a value we'll do not started now this is we can do this as kind of an example of how this could be different although not much different so here we could do not started with capitals and here lowercase or whatever you might want to do do a second option third option this one we'll do started started this one let's do done done that's our select box and then finally we are here let's do our input type equals submit class name now luckily we already typed all that right BTN and the value equals this will be dynamic in a little bit so it can be update ticket but for right now create ticket okay let's take a look at what we got cool so depending on um if you want this button wide or not that could be different but other than that it looks pretty good make sure everything works looks like we can select stuff change stuff type that looks great if you wanted to change this button to look more like uh like a smaller button you could do like a Max width of extra smaller something if you go here now it's more like a button doesn't particularly matter to us um but if you want to change it so what we're going to do next is we're going to actually hook this up and then we will create our our first ticket in the database so let's see if we can get a ticket actually submitted so let's scroll up and we're going to edit our handle submit here let's go ahead and delete that out the console.log we're going to get an event so we'll pass in E we're going to prevent default so the first thing we want to do is we want to prevent the form from doing its normal default Behavior so we don't want the page to refresh or anything like that and then let's create a constant for our response we'll set it to await fetch we're going to go to our API to the tickets folder oh we didn't create a ticket folder so our API we should actually create a folder for that cuz eventually we're probably going to have more than just tickets in our applications you're going to have users or whatever it might be so let's create a tickets folder let's move this route ins inside of that folder so go ahead and move it now we got a route inside of tickets so we'll do a weight fetch tickets this will be our URL that we're accessing for this post method so we'll say say our method is post our body we need to pass the data to this post method so we'll do string stringify and then we'll pass in our form data we'll do content type of application sljs that looks good all looks good there we'll get to that era in just a second ignore that for the time being we'll say if our response. okay is not true so if there's some sort of an error let's throw a new errror let's just say failed to create ticket now after this we after we create a ticket we probably want to Route it back to the dashboard to our ticket set so here is where we need to use this use router that we defined above so let's create a router so let's say const router equals use router and then here down below so this is going to throw this air if not if it doesn't throw that air then we want to use the router to refresh the page and then we'll use router. push to push us back to the default page so that all looks good this handle submit now because we're using an async function because we're waiting we need to use the async above save that that looks pretty good I think so let's go ahead and let's create try and create our first ticket let's refresh this page just to make sure and we'll say I dropped my PC please fix my PC I dropped it today I will be waiting your response we'll say this is a hardware problem give it a priority of two not started yet create that ticket and it through an air let's see if we have anything okay one thing we can do we can do control shift I this will bring up our console here status of 404 not found API tickets that's probably because of how we had it structured and I kind of moved things around there so inside of our API folder there's tickets and we have our route the post route inside of it let's do a console.log here and see if that hits we're inside the tickets folder go back to TI get form weot a slash here let's add that slash back in leave everything the same ah this import is now different because we move that so we need two SL two dot dot slashes to go back up two directories all this is because I didn't structure go back in our route so for our route we're going to add another do slash cool so that looks like it worked it kicked us back to the main page but you'll also notice that um it didn't give us the updated ticket which makes sense because we're displaying these default tickets we're not actually displaying our live data so if we go back here we can see that we've actually successfully created a ticket so that's cool I dropped my PC blah blah blah let's go back here and actually in our route I'm curious if I can replace this whole mess with at and then app slm models like that that should take us to the base of the app let's try and create another ticket and just see if it works I dropped the server this is way worse please fix it now this is also a huge problem let's make this a five and create the ticket you'll see that worked as well so that at symbol did work for us that'll probably clean it up so if we move things around it won't be an issue next time and you'll see now we have two tickets awesome so now we're creating tickets in our database so we got to create function down of our database but we're not showing those tickets we're still showing the default tickets here so let's go ahead let's create one more create a map of our whole network we'll create something like this we'll say it's going to take some time we'll make this a project we'll give it a priority of two we might already have something done so we'll add a little progress and we'll say it started create the ticket so now we should have three tickets two different categories yep and that's in our database as well so that's all good to go now what I would like to do next is let's create a route to get all of our tickets cuz cuz right now we're showing default tickets but we don't really want to show default tickets we want to show our actual tickets that are stored in our database so let's create a new async function for get now this is inside the tickets folder in our route folder we can do a try catch for this as well our catch can be the same so I'm going to copy that paste it so we got our catch and then here to get the tickets we're going to do const tickets equals a weit ticket find we're just finding all of them you could do some filtering here you know only find Open tickets only whatever but we're not we're not there yet so we're going to keep this the same and when we do that we want to return a next response instead of this we want to return our tickets and we'll give a status of 200 that's it pretty simple so now we should have a way to get our tickets into our project and let's go to our main page so inside the app now this can get a little confusing because we have multiple Pages um but inside the base level app where we're displaying our ticket cards let's open that up and the first thing I want to do is create a con to get create a variable to get our tickets this is going to be an async function because we got to wait for it we don't need to pass anything to this one right because we're just doing we're just trying to connect and grab out the tickets this will be a good look so let's create a const for our response equals a weit let's fetch our tickets this time we're using the server we're not using client s side so we have no used server up there so we need the full URL I believe to API make sure this is capitalized tickets so this should get our response do a comma inside here we just want to ma mention that we don't want to store this data so every time this runs we want to check and see if there's no if there's new data inside of this if there is we want to Res turn that response like that and if not we can console.log out our err you can make this a little more descriptive failed to get tickets that looks great right so now here inside of the dashboard we need to actually use that new function so let's destructure tickets from await get tickets this dashboard needs to be an async function Willow wait get tickets so now we should have our tickets now I want to map over and get all the unique categories we have so I want to kind of separate out these tickets by category so buy software buy hardware and buy projects in our case um we don't have any software yet I don't think but we might in the future so let's get all of our unique categories let's set that equal to an array what we're going to do is we're going to D structure a new set so what set's going to do is it's going to take all of our results and it's it's going to remove the duplicates essentially so we're going to do tickets. map we're going to destructure our category singular and then we're going to return each time that category so all we're going to do is we're going to map over all the tickets and every time we have an individual ticket in our list of tickets we're going to grab out the cat ategory and we're going to return it then we're going to pass that to a set so what that's going to do it's going to remove the duplicates so now inside of here in our case we should have Hardware problem and project as our two unique categories we shouldn't have software because we don't have any tickets yet that have software so now inside of this we can delete out all of our placeholder ticket cards so in side here let's do another div and below this div we're going to say if we have tickets so if tickets is available we want to take our unique categories and we want to map over those for each unique category now make sure this is singular so unique category we're going to get the unique category and we're going to get a category index every time we have that we're going to create a function and every time we have one we're going to create a new div opening and closing and this div we're just going to give it some space here so mod margin bottom four and we also need to give it a key so we're going to set the key equal to our category index here just like that so this is going to give us whenever we're mapping over we need to give it a unique key a unique identifier so that's why we're passing in that category index and then inside of this let's give an H2 and this is going to be simply our unique category so it's going to give us a header of whatever category we're currently under then let's pull this out of here let's put it below that H2 so now we we have our new ticket grid here I'll save it just to format a little bit for you guys and now let's spit out our tickets so with our tickets we want to do filter we're going to grab that One Singular ticket and we're going to say if the ticket. category equals the unique category we're currently on not the unique categories singular so unique category so if the current ticket matches the category header that we're displaying here then we want it to show up right so if that's the case we want to do map and this is going to be our filtered ticket and our underscore index here now what we can do now once we get to this point we know we have a ticket and we know it matches our current category so now we can pass our ticket card like that but we also need to pass some more information remember our ticket cards are static right now we're not passing in any actual data so we want to give it an ID and the ID is going to be underscore index and the key is going to be underscore index and we're also going to pass it the ticket information which we'll call ticket pretty easy so now we're passing all of our information into here now remember this ticket's still going to be static because in our ticket card we're not using this yet but that's okay we will be here shortly so we can save that and we don't want to pass ticket here we want to use this filter ticket I could tell because it was gray out we want to get just our filter ticket that would have been a weird bug later and you can see now although the ticket information isn't correct you can see it's updated to fall under Hardware problem or project and we have three tickets which does match the amount we entered so we're getting closer so now we're actually passing this data to our ticket card we need to update that ticket card to utilize that information instead so if we go to our ticket card now we're being p a ticket to this so we can destructure you're going to use your curly braces here and we're going to destructure that information and then the first thing we want to do is priority display so for priority display we want to now pass in our priority that we want to use and we want to use ticket. priority so now inside of this priority display we're going to utilize this new one instead of hardcoding it so what does that look like if we open that up and you can control click on this to open it up or you can open it up over here I'll control click if you open this up now inside of our priority display we can destructure the priority that we were just passed in now with that priority we can dynamically edit these so they're not always all red we want to use that priority value so if we want to do that we can switch these to back ticks let's switch these to back ticks and then I'm going to wrap it in curly braces so now we can add variables inside of here so the first thing I want to do is let's add some padding to the right of one and then we want it only to be read if it's a priority one ticket so let's use these curly brackets and we're going to say if our priority is greater than zero if our priority is greater than zero we want this ticket to be red otherwise we want it to be some other color let's get this just so it's a little easier for you to understand here okay so we got a conditional statement here so if this is true this first quotation mark is going to happen so we want it to be red if it's not true then we want the text color to be slate 400 so this is just going to be like a gray so hang with me here this is is a little bit different but let's copy all this and let's replace all of these so now if our priority is greater than one we want this one to be colored if it's greater than two we want this one to be colored three and four we want this one to be colored so now we're using that priority information that we're passed in and if you look at these they all have zero priority which isn't great right that's not correct because we didn't save our ticket card let's save that and now you can see it's Dynamic so this part should be updating so we have a hardware problem one has five stars and one has two stars and if we go here we have a hardware problem one has five stars and the other has two stars so that that makes sense or two fires stars and my fires so the priority display should be hooked up let's go back to our card right here we can go ahead and update our ticket header as well so let's use curly brackets and do ticket. tile here we can do curly brackets do ticket. description those should update now see now we're getting Dynamic data here as well our statuses aren't correct or progress bar isn't correct that's okay we got to go back and create a delete block you can't delete tickets right now so we got our title we got our description for the time this one's going to be a little unique it's going to be a time stamp right now but let's use curly brackets and let's do ticket dot look at our database it's called created at you could use the update as well I guess created at so that should show up now you'll see we got this pretty time stamp we'll deal with that in a moment and our progress display we want to pass in our progress so that progress will be equal to ticket. progress and our status is the same way we want it to status equal ticket. status so now these won't show up yet obviously we have to enter the actual data on the ticket so let's open up progress display following the same format we want to destructure our progress and now instead of hardcoding in 75 here so instead of hardcoding this in we want to use fatic and then we can do dollar sign and pass it whatever our progress variable is we still need the percent here so that should be done go back to our ticket card control click our status so here we want to use our status instead so we're destructuring our status and then here instead of done we want to be whatever our status is now if we look at this I remember only one had progress on it so that looks like it's correct and you'll see not started and started are both correct so the statuses are correct however they're not the right color so we got a little more work to do here you do this a bunch of different ways let's create a function let's say this is get color we're going to pass in the status that this equal to status like that again we'll create a color so we'll say let color equals we can do BG slate 700 as our default and then let's do a switch case so we'll take our status and Dot to lowercase this just to be careful in case we get past an uppercase status or something like that now here we can have a case if it's done we want the color to equal BG D green-20 which is the color it's using right now let's go ahead and return that color then our case if it is started so we'll say that case is the color will equal dg- yellow -200 then we'll return the color that a p in there contr s we'll get all formatted you're noticing I'm getting sloppy because of this prettier we say not started as our last status the color will equal BG red 200 because we need to start that as soon as possible we'll return the color and if none of these execute we can just return the original color that we set above oops don't put that there after your switch case so one of these returns should hit in our case if not we just do the gray um background default or whatever it is there now if we slide over now we don't want to hardcode in this 200 right so we want to utilize our function so what we can do is change these to back ticks like so make sure you delete out the extra one we can highlight all of this put it inside curly brackets like that we want to delete out the background color of green we don't want that anymore we'll do dollar sign curly brackets so now we can inject a variable here we can do get color we can pack pass in our status that should be it so it should look something like this get color and status with it wrapped around like that let's see if it worked and now we got our correct colors we are making crazy progress here so we got our priority we got everything on the ticket formatted except the date time I'll show you kind of a neat way to take care of that so back in our ticket card let's create a cute little function to format our timestamp so let's let's say const format time stamp equals we'll pass it a timestamp do something like that so for this we need to set some options of how we want it to look so totally up to you but let's do year of numeric let's do month of two digits so we'll do a two-digit month let's copy this we'll do day hour and minute so after month let's do day hour and minute and then let's also after this let's say hour 12 equals true so this is going to give us the options of how we want our date to look again obviously you can do whatever you want let's set a con date equals new date and let's pass in our timestamp so now we have a date object that matches our timestamp that we set and now let's format it formatted date equals date do2 local string like this en. us or whatever you want to format it to let's do comma then pass in our options now the most important thing in any function if you need data back is returning the data I don't know should this not have two T's that spelled right formatted I don't think formatted has two T's so we're returning that format a date so now in instead of using this pure timestamp here so we use this ticket created at instead of that we can call our formatted Tim stamp and pass in that Tim stamp now if we take a look at this this looks much better so now we have our tickets working we have all the data showing up we can create tickets now we need to be able to update and delete tickets as well so that's what we're going to cover next all right so we still have two functions of our crud application that are not functioning yet we need to create our delete function and our update function as well let's go ahead and Tackle delete first I think it's a bit easier let's go back to our code into our API now this one's going to be unique inside of the API folder let's right click on tickets and create a new folder and for this one we're going to use the square brackets and ID again so what we're doing here is we're going to create an API that can access and delete a single ticket or delete or update a single ticket so we're going to use these Square params again and if we right click on that we're going to create a new file and we're going to call it route doj again the name is important there so we have one route. JS inside our ID folder and we have one inside our tickets folder now the Imports are pretty similar so let's do import ticket from we can use our at symbol this time app slash models ticket that looks pretty good and then we'll also import next response from next server that looks good this one's pretty simple so it shouldn't take too much here we're going to export async function delete we're going to use request and we're going to grab off the pams so we want to grab the parameters that we're passing in so we know which ticket to delete we can do this inside of a try catch like we did with our others if there's an error we can just return that response like we did with the others we can give a message of error and we can also pass the error we can also return a status of 500 or something like that that can be our err block for this we want to grab off the ID from our prams then we want to await ticket. find by by ID and delete and we want to pass the ID then if that's all executes we can do next response again we can copy this for our message we want tiet deleted don't need the erir we can give a status of 200 so this should be our delete function now we need to actually hook this up and make it function so let's go back to our delete block here and we're going to create a delete ticket function it's going to be an async function just like we did with our other ones inside here we can do constant for our response it'll equal a weight let's Fetch and then we'll pass our delete API URL so it's local 3000 API tickets plural in our case slash and then we want the ID now this is where you have to make sure your folder structure over here is okay and correct we want this route inside of the square bracket ID so then from here we can pass in our ID value for whatever ticket we're working on now it's also important for our delete Block in general we're going to now have to pass it an ID off of that as well so we'll have to update that on our ticket get card here in just a moment so we got our response oops I wasn't quite done there put a comma after this do our method is delete and we'll say if our response is okay want to do router. refresh this is going to be lowercase and we got to create that variable just like we did with our other where we created a router so we'll say con router equals use router now this is the one again you want to be careful we want to import next navigation use router so you can see my import is next navigation make sure that's the way on yours too or else it won't function correctly now we need to call this function so we'll say on click equals delete ticket bam now this is functioning but we're not at the moment passing in an ID so we're going to have to fix that so let's go back to our ticket card and inside the delete block now we need to pass an ID so we can say the ID equals our ticket doore ID so this is saved inore ID in mongodb save that let's go back to our delete block we have an error here um this is because we're trying to use an interactive component so we need to use client side JavaScript so we need to explicitly say we want to use the client up here to take care of our issue that looks pretty [Music] good so now if we go back to our application and I've actually had this sitting for just a bit so I'll hard refresh it just to make sure so that looks good we have our project and our two tickets let's delete the I drop the server ticket can't resolve the tickets go back here that was in the delete block I believe oh wait no it was in the route here oh silly me I needed parentheses around this my bad okay so if we go back here refresh this make sure we're all up to date we should be anyways H that we get another error router. refresh is not a function silly me this use router should be a function that should resolve our issue there so now this might have executed because it hit that so yeah we did delete it and then it aired out afterwards so we we did delete that ticket let's delete the project one and you'll see that works correctly we refresh we only have one ticket now if we go to mongod DB you'll see reflects that in our database as well we've successfully deleted those tickets awesome so we should be good to go there that is functioning correctly now we have just one more to functional component to add to our crud here and that's the update functionality so we're going to do this kind of uniquely I only want one ticket page so we're going to decide whether it's whether we need to update a ticket or create a new ticket based on the parameter we're passing in if we go to our ticket card first we want to add a link to this so when we click on a ticket we want it to take us to the update ticket page right so on our ticket card we need to add a link here so what we can do is we can wrap this whole section in a link tag so let's start the link right above the H4 and then we'll do it right below the status display here so there should be one div after the link tab if we save this it's going to puke because it needs the hre here so we'll go ahead and set that up so we'll say hre equals curly brackets back ticks because we're going to use some variables here we want it to go to the ticket page now remember we have to pass a parameter to go to the ticket page because it's in that ID so in this case we want it to give the ID of the ticket and we want the style variable here as well so what we're going to do is we're going to pass in to make sure it displays contents so essentially this is going to allow our CSS to pretty much ignore this link tag so it's not going to change the structure here we're just adding in the link is all we're doing and of course we need to import this I'll use intellisense there you can see it added my link from next link that should be good that should be working so now if we go back to our application we only have one card we're running out here you'll see I now have like the pointy Arrow over the whole thing if I click on it I do go to the ticket app so that is a positive we go to the ticket app we have the correct ticket ID but obviously it doesn't look like we're updating it it still has create your ticket create your ticket and we don't have any update functionality either so when we click on this remember we're going to the ticket page so inside of our close the components inside of our ticket page folder we have an ID folder and then the page here and right now we're just rendering that ticket form we're still going to pull off the pams we definitely need those now and then inside of this we're going to create a constant called edit mode so this is going to tell us if we're editing a ticket or if it's a new ticket that we're cry trying to create so remember if it's a new ticket the ID will equal new otherwise it's going to be something else so we can set up some conditionals here so all this is doing it's going to check our parameters to see if it equals new if it does update mode is false and we know or edit mode I'm sorry so we know that it's a new ticket otherwise edit mode is true and if we look at this we can tell that see if we had ran this edit mode would be true because this does not equal new but if we use the new ticket button you'll see on the same page we have a pram of new so that's going to be what drives whether this is updating a ticket or creating a new ticket so let's go ahead and say if we have edit mode so if we're editing a ticket we need to get our update ticket data we'll set a variable for that as well so we'll say let data equal blank object like this so then if it's edit mode Let's go ahead and create a function to get our ticket by ID now technically we could probably pass all the tech ticket data down from the function above but I wanted to do this so we can show how to get a single ticket we have a function where we're getting all the tickets let's create one to get a single ticket so we're going to await that ticket data remember this function doesn't exist yet and then down here we can just console.log out that updated ticket data for right now we obviously don't have this function and this needs to be async now then up here we can do const get ticket by ID this equals an async function we'll pass in an ID we can do our try catch if there's an error let's just console.log out that error for right now we'll await our fetch let's use back ticks again cuz we're going to pass in that variable HTTP localhost colon 3000 slash API slash tickets slash dollar sign ID this doesn't exist yet but a comma curly brackets and we want to not store this data so we want to grab the data every time to no store that looks good let's do it this way actually instead of the try catch block let's say if the response isn't okay and we want to throw a new air failed to get ticket so we can actually kill this try catch that and we'll just throw a new err if we don't get it otherwise we want to return our response. Json like that okay so now we have this all but this API does not exist yet so we need to create that don't worry it's very easy so we're inside the route. JS inside the square bracket ID folder remember that's very important we're needing to use the ID again with this one so on top here let's create export Port async function get we're going to get some requests we're going to get pams this time as well off of those pams we can grab our ID very similar to what we did for the delete we'll grab our pams we can get our found ticket data and set it equal to await ticket. find one where the underscore ID is equal to the ID per Ram we grabbed above so it's going to find our specific ticket and then we want to return next response. Json let's return the found ticket and let's also return a status of 200 I guess to stay consistent we should put this in a try catch as well let's copy all this Jazz put it inside of our try and then our air is going to be the same so let's copy that paste that that looks pretty good okay so now we should be able to get our ticket data and it should console.log it out now this is going to be on the server side so it should go in our terminal inside Visual Studio code I think click on that goes to this page that all looks good and you'll see it does have our found ticket data now you'll also notice it's inside a found ticket variable here so if we go back to our ticket page so let's go back sorry guys I need to start closing out of these more often so on here let's close out of our components close out of our API for the moment our ticket page we're going to the one in theore ID so we're opening that up you can see we're getting our ticket by ID that worked we console logged out this data here now was in a found ticket variable there so we can actually do if we want to just do something like this State ticket data equals dob ticket that should work little dirty so now this should have our ticket data that we can pass down to the ticket form otherwise if it's not edit mode so if we're not editing a ticket we just want our update ticket data to have an underscore ID of new and then either way we're going to pass down the ticket data to our form so now no matter what we're passing it into our form so now on our form so open back up the components open up your ticket form we can do some cool conditional rendering and we can either update or create a new ticket based on the ticket information that we're passed here so here we have our starting ticket data and below this we can update it if we're in edit mode so we need to create that variable as well well so we can do something very similar to our other program we can do edit mode equals ticket doore ID equals new this is false otherwise it's true we got to destructure our here as well so when it's passed in so our edit mode now if the ticket ID equals new and we know we're not editing a ticket otherwise it's going to be true because we are editing our ticket so now we have our starting ticket data this is for a new ticket so what we need to do is we need to check if we're in editing mode if we are in edit mode then we need to update all these values so if we're in editing mode mode our starting ticket data. tile is going to equal ticket. tile we're going to have a few of these so we'll have description priority progress status and category so we'll do description priority progress status category so now those should all work and now we're making this change before we create the state so the state should be updated if we're in edit mode here so we got I dropped my PC and then if we go here you'll see that we are looking like we're editing this ticket now we don't have any functionality to actually create to actually edit the ticket yet we don't have an update function so we're going to do that next but let's do some conditional rendering here to fix this so it looks like we're updating a ticket so if we scroll down we have this H3 that says create your ticket let's make this a bit more Dynamic depending on if we're editing or creating a ticket so let's put this inside curly brackets this is eventually going to be a string to create your ticket we'll put that inside of quotes now we need to do some conditional rendering so the first thing we need to check is what is edit mode set at so if edit mode is true so if edit mode is true remember we want to update your ticket and then we'll do a colon there and if it's false we want create your ticket to show up now let's copy this and we're going to do the same thing for our submit button more or less so submit the value currently is create your ticket we want to make that Dynamic and we'll say that's update ticket if it's true or create ticket if it's false so now if we go back to our project you can see it's update your ticket update ticket so this looks a little better and now we're showcasing that we're not just creating a ticket here we're updating a ticket if we go to a new ticket so remember clicking on this goes to the new ticket you can see we don't have an iore ID on your ticket go back here to our [Music] page let's do this let's console.log out our edit mode and let's also do our update ticket data see where we're messing this up update mode is false our underscore ID equals new that did work now maybe it just didn't hadn't updated yet if I click on here we got our update ticket go back here yeah that's working now must have just not updated correctly so we can delete this out it is functioning that looks good so now let's go back to our ticket form we need to change some things right so obviously in our handle submit here it gets a little more complicated now right we don't want to just post our new ticket every time because right now even though we say update it's not going to update the ticket it's going to create a new ticket still we need to fix that so essentially this first line is going to stay the same regardless and we want to refresh and push our back to the dashboard regardless so everything else will go inside an if statement so if we're in edit mode we want to do something else right we want to update our ticket else we want to do all of this Jazz that's how it should look let's tuck everything inside this lse statement for our creating of a new ticket and then we just need to edit our new ticket actually we can probably copy some of this it's probably similar let's copy that so now now we'll just edit this first one to be our update so for this we're going to the tickets folder but we're going one more directory because we have to pass in our ID so we do dollar sign like this ticket doore ID needs to be passed in now these need to be changed to back ticks so we can use that variable inside and then highlight all this and put inside curly no we don't need to do that sorry n this should be good so that looks good and then instead of the post we need to put so we're going to update our data content typees the same our body can be the same with the form data being passed in so that all looks pretty good I think actually simple fail to update ticket how about that okay now back to our API inside the ID folder remember we can't be on this base one we need the one that's inside of the square bracket ID let's create our update function I'm going to copy our delete paste it below I'm going change this to put we need our request we need our prams we need our ID still so that is good but now we need to get our body data so let's do const body equals await request. Json and con ticket data so we're going to pull it off of the body equals body do format data like that that all looks good now let's go ahead and get our updated ticket or update our ticket so let's do update ticket data equals await ticket do find by ID and update we're going to pass in the ID which we grabbed off our pams remember we're going to destructure our ticket data pass that in that looks pretty good for our success we just want ticket updated then we'll send out our air so that all looks great okay little scared to test it out but we're good so I'm going to go back to the dashboard do that did a hard refresh let's click our new button up here so let's say creating a new ticket let's create a report database this is a longterm project using a lot of resources good luck say this is a project I just want to make sure the new ticket is still functioning let's make it a priority of three and maybe over 50% we'll say it's started let's create our ticket you'll see that all looks good that's all still functioning but now I see this ticket is incorrect it needs to be more important let's click on it now I can make it a priority five and let's add some more exclamation points they were wrong it's actually not started and this progress should be zero update our Ticket No it actually didn't update so let's check that out so our new ticket functionality still works but our update did not work check out inside of our go back to our route let's try this too let's say before this return if all this is successful let's console.log out say ran we say our put ran five so our put function is running so this price sign simple but let's also check out our ticket data and make sure that's updating as well maybe we're not passing at the right data so on this one click here this one should have no period on the title and more exclamation points go back to our log and you'll see our ticket data is undefined so that's our issue when we're pulling it off the uh oh and you'll see I did format data instead of form data so now if we run this this should show up as something instead of UN def find and that will help us Trace back our air this might work this time let's do three exclamation points priority five progress zero not started that looks better so now we're updating our ticket three exclamation points five fires super hot project and you'll see that we're good to go there we can create another ticket just to make sure our stuff still works so say we spilled pop on my laptop won't work now no idea why you ever work tech support this is kind of how these tickets go so that's a hardware problem we'll say it's five not started boom create ticket goes in the correct category looks good that's a pretty good setup right here we got our create read update and delete all functioning this is a great place to get to on this project now you know the understand and understand how to use the app router and nextjs 13.4 this is not a production ready application right now we're sharing tickets with anybody who goes to it and it's unprotected we need to add authentic ation and a bunch of other stuff as well if you'd like to see me continue and update this project let me know in the comments if you want instant access and questions and being able to suggest new projects and see updates to this code that you guys might fix in the future visit the website and join it's free you get early access to videos and this is the only way to request certain projects for me to do and showcase to you if you don't mind and you've enjoyed this video so far please hit that subscribe button my daughters really want that silly little plaque for subscribers so if we could get to 100,000 subscribers that would be awesome I'm going to continue making videos for you guys regardless and until next time keep coding
Info
Channel: freeCodeCamp.org
Views: 111,703
Rating: undefined out of 5
Keywords:
Id: H0vhkoXljq0
Channel Id: undefined
Length: 148min 32sec (8912 seconds)
Published: Fri Oct 20 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.