[Music] hello and welcome I'm Dave in the previous lesson we Define schemas and set default values for our react hook forms in today's lesson we'll create typesafe form inputs that will provide client side validation and give users immediate feedback I'll provide a link to all resources in the description and I'll also provide a link to join my Discord server where you can discuss this nextjs full stack project with fellow students ask questions and help each other out heyy guys a big shout out and thank you to Sentry for making this full stack nextjs educational video series possible Sentry is defining debug ability in full stack web applications and I consider Sentry to be an essential part of my text stack from error reporting logging and tracking to identifying performance issues with tracing to user session replays and much more Sentry will help you write and ship code that delivers exceptional user experiences follow the Sentry links in the video description or just visit sentry.io and use the code Dave gray to get 3 months of the Sentry team plan for free in this nextjs full stack project series I'm using the same Tex stack that I've been working with on a major project at my job over the past year for viewers students and subscribers that have asked what I work with on a daily basis this is definitely the tutorial series to watch I've got vs code open and we're looking at our user stories for our repair shop app and much like the last lesson we are working on user story 14 and 15 where all users can create and view tickets and all users can create edit and view customers these are our goals for the tickets form and for the customers form so let's continue with that today by creating new inputs that we can populate our forms with and those inputs are going to provide validation and give the users immediate feedback let's open a terminal window by pressing control and the back tick and to create these inputs we're going to need to install some Shad CN components so I'm going to type npx need the N first there we go npx Shad CN at latest and then I want to type add and now we'll type the names of the components we need we need input we'll also need select going to have a text area and a check box now Shad CN now currently supports the new version of nextjs that's nextjs 15 that's stable now it also supports react 19 but it's going to ask us some questions as we go through this so I'll press enter okay when it asks how would you like to proceed I'm going to choose use Legacy peer depths and press enter now it should complete installing those four components that we need to create our inputs so we've got input select text area and checkbox now now while we have a terminal window open let's go ahead and start our project with npx I'm sorry npm runev and this should start the nextjs project in Dev mode and we can launch it at Local Host 3000 and then we'll need to go to the either the login page if you need to log in or if you're already logged in you can go straight to the slash homepage so we'll pull that up here it takes just a minute to compile but not too long and we've got the homepage up now so I should now be able to go to slash login if I need to log in and if you do need to log in you're going to have to enter in your email address it's going to email you the code so I'm going to quickly enter mine with Dave DAV gray. codes I recently had somebody send me a code at this email address remember to enter your email address not mine now I'm going to enter my code as soon as I receive it and I'll meet you at the homepage of the app and I've launched the app I'm in dark mode and here we are at the home page now that I have logged in now let's quickly look at the Shad CN website for forms and I have clicked on form not react hook form specifically but in the left hand side where Shad C lists the different components I've clicked on form over here and this is the page we get but he talks about using react hook form I looked at this briefly with you in the last video because I talked about why I was choosing to use react hook form and I'm using Zod as well but now I just want to to show the examples here and when we look at the anatomy of how you create a form component with shad Cen using react hook form it looks like this now for every input we want to have on our page if you can imagine say the customer page where we have the first name last name first line of the address second line of the address city state ZIP and so on you would have one of these essentially for every one of those inputs now that can get kind of cluttered so what it would be better to do would be to create one component one input component if you will that we can extract then we can just import it into our form and it won't clutter up the form component and then of course we'll have this in a separate component so that's what we're going to do with those four different inputs that we installed we have input we have a text area we have a select and a checkbox so let's get to work back in VSS code on our input component and you'll see how it all works with react hook form okay we're back in vs code I've got the file tree showing over here let's go to the components directory that we have in our project here it is inside the components directory you should also have a UI directory and that's where Shad CN installs the different components that we have added to the project I want to create another new directory inside of the components directory and I'm going to call this one inputs and then inside of the inputs I'm going to create my first component I'm going to call this input with label . TSX and this will be our form input so I'll start with use client all of these will be client side components then I'm going to import use form context from react hook form and the Ed form context is going to let us pull in the form and reference it inside of this separate component so it doesn't all have to be in the form component that we were creating then we can import this back into that form component okay after that we need several things from Shad CN so we'll just start the list of imports here we need form control we also need form field and then we need form item and then form label and finally form message okay all of these are going to come from at SL components slui SL form okay but we're not quite finished with shad CN yet we also need to import the input component that's going to come from at SL components SL input not inputs just oh we need the UI there we go uiinput and finally I'm going to import input HTML attributes that comes from react and I'm doing that because I want to extend the props so I can send other props into this component if I want to so those are our Imports to start out with now let's go ahead and type out the props that we're going to pass in so I'm going to say type props equals and some people prefer to use an interface I like using props it's what I usually use and I'm going to use a typescript generic here also and this is going to help our type safety so I'm going to say s here sometimes you see t as well so you could use that if you want to I'll say s and then inside of this and by the way s is for schema because that's what I'm going to pass in to make sure that the uh input matches or the Val validation input matches what we have available in our form so you'll see how that works in a moment but first let's put in our Field title prop that will be a string and I'm going to say name in schema and this is really what we're matching here with that generic so I'm going to say key of s which is a key of our schema and it's going to be a string then class name so if we want to pass in any classes we can so this will be optional that would also be a string but then at the very end since I also want to possibly pass in other props that are just natural to the input I'll add that input HTML attributes and we'll say this is an HT tml input element type that will let us spread in the props and so anything else we would normally pass to an HTML input we'll be able to do so okay so now we have export function input with label is what we're calling this and it will receive that generic so that's RS again for schema right there and now we'll get the props here so we'll have Field title we also have name and that we listed above we'll have class name and then we'll spread in the props as well hey after that we still need to have props here after our destructured object here so I'm going to say props and once again we need to have that generic there as the s for the schema okay now we're ready for the body of our function oh and by the way I should say I know generics and if you haven't worked with them a whole lot uh don't let this freak you out I'm going to show you how easy it is to just pass in our schema here and match everything up so it'll just give you a little extra type safety with these inputs okay now I'm going to say const form and I'm going to set that equal to use form context so this will let us reference our form inside this component and now we're ready for the return which is essentially that anatomy of the form field that we saw in the Shad CN docs so I'm going to say return have my parenthesis here and we'll start off with our form field component from Shad CN and it has a control prop we'll set that equal to form. control and after that we're going to have the name and that's going to be equal to the name in schema that is passed in and then we're going to have a render method here so we'll have render equals and inside of this we'll have an function and there we can destructure the field here from react hook form okay now we'll have an arrow here for our our Anonymous function and let's go ahead whoops not a curly brace but parentheses now and inside this parentheses a lot of things are going to go in here so let's go ahead and start with our form item it has a closing form item tag that's correct now we'll have our form label now the form label have a class name we're going to set this equal to just text base here and then an HTML 4 just like a 4 attribute would be on an HTML element in react we use an HTML 4 this is going to be the name in schema once again and then we can close out our form element and now this or our form label element and this is where we'll have our Field title that is passed in so that actually what would be seen on the screen for the label now after that let's come down an extra line there and let's separate this so we'll have our form control now inside the form control we're going to have our input start the input go down to a new line because it's going to have several props one is the ID now this needs to match whatever the HTML 4 is so once again it's name in schema after that we're going to have a class name prop here I'm going to set this equal to well first we'll have curly brackets but then a template literal string going to hide the file tree so we have a little more room and this is worth a little bit of discussion because we can pass in the class name here it's optional so if we want to add more classes but because I'm not creating a component Library this is a specific application I have some classes that I pretty much always want to apply to these inputs or any text input like this one and so I'm going to put them here but then we'll put class name at the end of the list and that will let us overwrite any of these classes that we put in in case we want to or we can add classes to it anytime we want to so now I'm just going to put in the classes that I'm probably always going to want to apply so I have width full Max width set to extra small then I'm going to set some colors here that are just going to match what I plan to do with the application these might be ones we would want to override at some point but they'll also be just specifically for if the input is set to disabled we'll have text- blue- 500 and if we're in dark mode and the input is disabled then we're going to have text- green- 500 I'm going to press alt Z to wrap all of this down after that one more disabled going to have an opacity equal to 75% and now I'll just pass in that class name that will let us overwrite any of these classes or add to them if we want to with this component okay after that we still need to spread in the props that are received above and we need to spread in the field and this field comes from react hook form right here in this render method that we're in the middle of creating right now so there's the field we spread it into the input that handles the on change and other things that you would expect the input to have working inside of react hook form so we don't have to specify each one of those now we're almost finished but we need to put in that form message that we imported as well and this is where the message would go if we have a validation message if something isn't right we're going to give the user that immediate feedback okay after the form item and we've closed out the render method here then we need to close out the input itself so we put a slash and the carrot there and or the greater than sign I should say and that closes it out and we should be finished with the component so let's go back up and see where all of this started we're in the return here so that's where the parentheses are come down we can see the end of that so we just closed out this form field with this slash greater than right there okay and that is the input component let's go ahead and put it to work inside of the customer form let's click on the file tree over here to the left and if we scroll up we can go to our app directory that has the RS directory here in parenthesis and then customers form and there we should find the customer form that we were working on before I'll press contrl B to hide the file tree once again so we have some extra room there and just after our button import that we haven't used yet but we will let's go ahead and import the input we created so I'll say import I want input with label it comes from components inputs and then the input with label after that let's scroll down to where we started the form in the previous lesson and here we can see the form component from Shad CN and currently we're just stringifying the form values inside of the body here and we don't really have any inputs so let's change that but first I want to change something just quickly here inside of this class name that we set on the form in the last lesson I had set this break point here at small I want to switch this to medium and that means I also want to switch this one to medium everything else should stay the same okay after that we're ready to go ahead and add our input to the form well I actually want to put this in columns because we're going to have more than one column so the First Column will be a div let's give it a class name let's set the classes here we'll have Flex it will be fle x- column give it a gap of four width is full and then the max width let's set max W and then let's put that EXs there for extra small once again and if I Mouse over that you can see that's 320 pixels is what that Max width XS is okay now we have added the classes we've got the closing div so this will be the first column in our form now notice it's set to flex columns so that means we'd have one big column still when we're on smaller screens but once we we reach this medium breakpoint which is 768 pixels the same as an iPad in that uh tall mode they're not horizontal mode but vertical um then it will switch to columns in an iPad but on a phone for example it would all be stacked in one so that's the layout we're going for and of course you'll see that here as we put it all together so inside this First Column we'll have our first input the input with label and right after that we need to pass in the schema and the schema we're using is the insert customer type schema okay let's come down a line and we'll have a Field title prop that we can pass in here we'll set this to first name and after that we'll put name in schema and this is where it needs to match what we have in the react hook form default values here so it's first name if I choose that I can put that in here and afterwards I'm not going to pass in any extra classes so that's our input now notice how that matched if I switched this to something else and just said Dave now we get the red squiggly here it's types safe essentially it's correcting us saying hey that name is not in the schema and that's where we passed in our here as that generic and so it's making sure we're putting in valid names so the only names that'll work are the ones that are the keys in this schema so let's undo that contrl Z and now typescript is good with that no squigglies and everything's okay so we can go ahead and put a few more inputs in our form and then we'll check out how it works so I'm going to select all of this then do shift alt and the down arrow and now I can switch first name to last name so that's an easy one I'll select the first one control D to select the next one I'll type last and it's replaced both make sure you have the casing correct as this is a lower case this is an uppercase and of course this has to be an exact match to the schema for typescript to be good with that okay after that we're going to have an address one and an address two so shift alt and the down arrow once again I can switch this to whatever we want the label to show is what would go here so I'll put address one and now down below we need to match the schema once again so I think that was address see address is no good but address one yep that's good now let's go ahead and put the next one in should be address two I'll select number one control D to select the next instance and press two after that I think we're going to go ahead and fit city and state yet in this column so let's go ahead and copy this down here and I'll do it again shift alt and the down arrow so I've got two of those I'll switch this to city and this would also be City and then we're going to have state but really let me go ahead and delete this because that's where we're going to use a select input so we'll wait on that that let's see how these look so far inside of the column inside of the form so we need to go check that out in the browser when we go back here to Chrome we'll go to our app now we're at our homepage we need to go to the customers page so to do that need to go to customers SL form go ahead and enter and see what we get here so we've still got our stringified data out here to the right and this is a new customer form but here are the inputs we created over here in this column so let's check it out now now first name is required if you remember setting up the schema we did for our insert schema so once I Tab out of here and don't enter a first name we get that instant feedback it turns red it says first name is required whatever message we set here inside of our schema is what will show as well so we could change this message if we wanted remember when we did that with Drizzle Zod we were actually putting in those messages for the required Fields likewise last name is required address one is required address two wasn't required so when I Tab out of that no problem City that's going to be required as well so this is all working as expected let's put in the rest of the inputs that we're going to have here as far as our input with label goes in the customer form and back in vs code let's go ahead and scroll up to copy this beginning div here from the First Column so we can start our second column just underneath that so underneath the closing div I'll paste that in and start a new column here let's add the closing div as well save for the formatting I'm going to delete the line that has Json stringify with the form values as we'll no longer need that now let's copy one of these input with labels here contrl C to copy and we'll paste this in below so we don't have to retype everything contrl V to paste contrl s to save and now I've got the formatting I want but now I've got a duplicate input here for City so let's switch this to what we expect to see in the second column we'll start with zip code and I believe the name in the schema was zip now I can copy that down shift alt and the down arrow the next one is going to be email and we'll turn this into a lowercase email should match the schema hey let's copy this one down shift alt and the down arrow once again this should be phone so I'm just going to double click then control D to select both type phone make sure the casing matches though as well because you want lower case here to match the schema that needs to be identical this is what we display here with the uppercase and the Field title value okay after phone we're also going to have a text area which we haven't created yet that will allow us to have some notes and then we're going to have the submit and reset buttons so let's start working on that area I'll put a div wrapper around both buttons and set a class name here of flex and GAP to two I want this to be a row because we want the buttons side by side so now we're going to use that button component that we had imported from Shaden we'll set the type equal to submit and now because this button is inside the form anytime you do that with a submit button you don't really need an onclick Handler this will call the onsubmit function of the form now I'll also put in a class name going to set our submit button with a width of 34 so it'll be the bigger button of the two inside the div we can set a variant equal to default and let's set the title equal to save that's just when you Mouse over and have your pointer looking at the button for example so let me go ahead and close the button out and inside of the button we'll actually have the word save on it as well let me put that on a separate line and then the button close on a separate line as well okay so there is our save button now we can copy this down also so highlight all of that shift alt and the down arrow so here is our second button now on this button clearly we're not going to set it to be three Force width also we had that before so this button will just take up whatever is left it's also not a submit button so its type will just be button instead of default here we'll set this to destructive so Shad CN we'll change the styles on that based on the variant we could also set an RA label if we wanted to or a title so we'll go ahead and have a title once again since we did that above and let's set that to reset now we're going to need an onclick here so I'll say onclick equals inside of this we'll have our Anonymous function we'll call form. reset we'll pass in the default values so it will just set everything back to the original default values for the form and we'll put the words reset on the form we save that now we should be able to go back and take a look our form isn't complete we're missing a text area we want we're missing a select input for the state dropdown but we have all of the text inputs just the input with label and that's most of the form so now let's go back into our browser and take a look it hasn't reset here yet from the validation that we had so we could just go ahead and enter in some information so once I type my name in and Tab out the error message goes away and of course the color changes everything looks good I'll just put in something 222 Street seems fine we don't need anything there put in Kansas City now if I Tab out of here it gives us a longer message remember we put in that longer message when we were creating the schema but it's fine it works here so that's fine we can put something in here like 1 2 3 four five for a zip code Tab out and that works email if I just put in Dave ah no good but if I actually put in an email like Dave at gr. codes that's fine phone number it tells us what type of format to use once we receive that validation so we could have 1 2 3-4 5 6- 7890 and all is well now here is the reset button so I can reset this form now and it will clear all of these out and just go back to the default so let me go ahead and try that and yep that's exactly what happened now if I have validation here as well if I have a message like that where it says something's required and I wanted to reset all the inputs I can do that with the reset button as well we're back in vs code again let's show the file tree and we need to scroll back down to our components directory and inside of components where we were creating inputs you can click on the input with label if you want and we need to create a new file here so let's create a new one let's call this one text area with label. TSX now keep the input with label handy I'll go ahead and contrl B to hide the file tree but we can click up here to switch between the two because we want to copy a lot of this and just make a couple of changes we don't need to type everything else out I'm kind of a slow typer but I can make these changes faster so I'm copying Line 1 through 19 here where we set the props going to move all of this over to the text area with label contrl V to paste that back in and now here at the top use client that stays the same importing use form context that stays the same importing everything here about the form from Shad CN with form control form field Etc all of that also stays now this is where a couple of things change right here so instead of input going to import the text area so this would be text area and it's going to come from the UI text area but I don't like the dots again as I have said before so I want to have the at SL components slui text area then likewise it's not input HTML attributes it's text area HTML attributes so text area HTML attributes and we are good with the Imports I'll copy that that and paste that right here for the props the text area HTML attributes this is also not HTML input element it is HTML text area element notice the cap on the a as well a capital A there it's a lowercase a here I'm not sure why the inconsistencies I'm not the one that named those but it's just worth noticing the details there okay for props once again passing in the schema as we will with all of these inputs we create we're going to have a Field title going to have a name in schema these are all consistent and we're going to have a class name that we can use as well so all of that has stayed the same so notice we didn't have to change much let's go ahead and start the function now with export function and we'll have text area with label it's going to receive that generic the schema and then here where we destructure the props we'll have to list them out Field title name in schema then class name and finally we will have the props themselves there okay after that we still need to mention the props here after the destructured object so it's props and it receives that generic s the schema that we're going to reference now here very similar to before so we're going to say const form set this equal to use form context so we can reference the form inside of our text area with label component now once again this is going to use that anatomy of a form component that we saw at Shad CN and we typed all of that out with the input with label don't really want to type it all again so let's copy what we have and we'll just change a few things as well just for the text area so let's copy the whole form field so that will go from the return parentheses everything in between contrl C there let's come back to our component and we can type return parentheses and just paste all of this in and make a few changes but we won't have to change much we're going to start off with a form field it's going to have the form control that's the same we'll use the same name in schema and we'll start our render method with the field likewise we're going to have the form item then we're going to have a form label that's going to use text and HTML 4 I want to add one thing here just because it doesn't seem to have as much space between the label and the input as the regular input and I don't know why the text area is that way but I'm going to put a margin bottom of two on the label for this one we'll still have the Field title here so now we get down to the form control and of course we're not using an input I'll press alt Z to wrap these classes in we're using a text area so so let's go ahead and use that text area here instead of the input now we'll have an ID that's named in schema I'm not going to apply these classes here so all we need to do to uh apply any classes here would be to pass the class name itself then we're going to have props and field here from react took form the props are anything we would typically pass in for a text area if we wanted to this field is related to react hook form it has the on change and things we would expect there everything else is the same so we quickly created this component and we can save the file now let's go put it in our customer form I'm just going to click on the customer form that I still have open up here at the Top If you need to find it in your file tree that's fine too but now we're back in the customer form uh component and above the buttons and below the phone input let's put in our text area with label I don't believe I've imported it yet so I'm going to need to do that text area with label and it's not going to have a whole lot that's passed into it oh we also need I should just come right back here let's copy this I don't like to retype that long schema name so I'll just put it right here and then we're going to need the Field title which we'll just set equal to notes and then we'll have a name in schema and I believe to match what we had above inside of our react backook form that is just notes now let's pass in a class name and here I'm just going to set the height h40 we Mouse over that we should be able to see that's 160 pixels so you'll be able to change the height to whatever you want because we can pass in that class name okay everything looks good except we need the import one way to import something in vs code if you haven't and you're down here like 100 lines into the code instead of at the top I can just kind of hover over this and choose Quick Fix and now I can add import so I'll just click that and it's added the import for me at the Top If I go look it is imported here just like we need so now I'll save the file and let's go to Chrome and check out our text area that is now part of our form here so maybe we want to shorten this up maybe we don't it is still draggable so if anybody one of the users at the text store wanted to make it bigger or smaller they could still manually do that if they want to also let me reload that and we'll get the form size that it's set to so that looks pretty good now it's not required so I can Tab out of it with no issue as well but we're getting close now all we need is our select input that will list out the 50 states plus the US territories okay back in VSS code let's open up the file tree once again and let's scroll down to our component compon directory that we have we can close that I just wanted to be on this level essentially so I want to close any of these directories honestly and I want to click on something like the middleware here so I can create something new in this same level and what I want to do is create a new directory and call this one constants now inside the constants directory which you can see is now positioned right below the components directory I want to create a new file and I want to call this States array. TS now inside of this file I'm just going to paste my contents but I'm going to tell you how I created it so let me first just paste all of this in and you can see it's an array full of objects and these objects have an ID and a description and then they have the two-letter abbreviation for the state or United States Territory and then the description is the full name so for example Al and Alabama you can see I've got export const States array and it equals this array that has all of these objects now here's how I created this and you could do the same I used AI I went to I can't remember if I went to chat GPT or claw because I use both at different times but I typed this I had this object and I said I need you to create an array for me that has an object for every state or United States territ teritory that's formatted like this and I gave this example because I live in Kansas so I just typed this one out so it created this for me after that when it provided that array I just typed export con States array equals and I was able to paste this in just like you see me doing so in other words you can do the same thing I did I don't need to show you how to use chat GPT or Claud you can figure that out if you haven't used those but there's different AIS out there that you can use they're great for generating data like this so I didn't have to look everything up I'm fairly aware of all 50 states and the territories and this was good enough for an example if this was very serious I would of course be going to the United States Postal website verifying I had each one of these absolutely correct so I'm going to save this and we're going to use this data inside of the select input so in the customer form we can choose which state or territory that the customer is from and now it's time to go back into our components directory and then the inputs directory inside I'm just going to click on input with label once again and scroll to the Top Copy these same 19 lines to start off with and we're going to create our select input so contrl C to copy that now a new file and I'm going to call this select with label. TSS X to start off with I'll just paste in those same 19 lines and we'll make a few changes so once again use client directive at the top use form context will be imported from react hook form we need all of the same form inputs from Shad CN as well after that this is where things change once again we're going to need select inputs and I'm not going to import something else here like we did for the input HTML attributes from react because the select input is more of a custom input it uses some different things than your normal HTML input would and those props don't line up exactly so I'm not planning on extending that out however let's go ahead and import what we need from Shaden for the select so we need select we also need select content select item select trigger and select value and all of those are going to come from at SL components slui select and that's all we need from Shaden for the select we can go ahead and create that first I have a second type I'm going to put here going to say type and I'm going to call this data object but just obj for short set this equal to an object that resembles what we have in that states array here so an ID that's a string and a description that is a string as well now we can use that in our props type here so we're still going to have a Field title and we're still going to receive the generic and have name in schema we'll also have the class name but before the class name I'm going to put in data it's going to be that data object type and then it's going to be an array of those objects so this is what we want to represent there and it will be the states array we can pass in to this component but if we wanted to use it for other data we would be able to as well let's go ahead and save these changes with contrl s and now I'll go back to the input label and in the past I just started typing here for the export function but this time I think I'm just going to select the entire function because there aren't many changes I'll contrl C and we'll just be able to make the changes we need so I'm going to paste in the function first and then scroll back up here and we'll change put with label to select with label after that we'll just make sure we've got our props correct and it's a little different because we have Field title name and schema and then it should be Data before class name then we'll have data I mean then we'll have class name but after that we won't be spreading in any props as we did previously with the text area or the input and then of course we'll have the props here and the generic so all of that still stays the same we're still going to define the form with use form context we'll still start a form field have the control the name for nameing schema and start the render uh function here as well okay after that we'll still start out with a form item and we'll have a form label it's going to have the text Base Class and use the name and schema it's still going to use the Field title so everything is still on par as we get to line l 50 at line 50 some things are going to change so I'm going to scroll for a little bit of room and I'm going to tab over here because this is where we'll start and this is where we put our select and now I'm going to come down to a new line and I'm going to spread in the field as you've previously seen me spread that in with the other inputs and then we're going to have an on value change and now this is going to equal field.on change so that's a little different we couldn't spread in that onv value change with the field here because this is just a little different so we pass in the field.on change to that on value change here for the select okay now we have finished the select here I shouldn't put the slash here before the greater than sign though I actually want a closing select later on so I've put the select here let's put the closing select where it belongs and that's going to be right down here before the form message so let's close it out right here SL select now when I save we should get the reformatting so we've wrapped the select around the form control now things will also be different inside the form control first I'm going to press contrl B to hide the file tree again then alt Z to wrap anything that needs to be wrapped and let's just go ahead and delete the input here inside the form control because here we're going to use a select trigger now the select trigger is going to have the ID and that's going to be the name in schema after that we're also going to have a class name here and here we're going to do what you saw me do with the input so I'm going to put a couple of classes and then put class name at the end so it could either overwrite these or add to them so we'll have width full Max width extra small and then we'll pass in the class name prop okay after class name we're going to go ahead and close out the trigger and then inside this trigger we're going to have the select value we imported we can put a placeholder here so this will display whatever we want when there isn't a selection so I'm just going to call this select okay now we've got our select trigger that's what we'll start the whole thing but now we also need the content for the select so we'll start our select content and it will have its own closing tag now inside of here is where we're going to map over the data so this would be our states array for example so now we map over this for each item in the array I'll put another parenthesis there we want to create a select item let me scroll just a little bit and now we have select item now each select item should have a key as when you map over items so this key going to put in a template literal and we'll think about this because this is something where you might use more than one select input on a page we won't be on the customer form but if you were to use it somewhere else maybe you would so think about that when you name the key so you don't have duplicate keys so we'll pass in the name in schema first so that should be kind of unique for that specific input and then we can still use the item . ID for example so when you combine those two it should definitely be unique even if you have another select on the same page after that let's pass in the value which is the item. ID and now let's close out the select item inside the select item though we want to display the item. description so that's what the user would read but the value that's actually passed to the form is the ID itself okay we should have a full select component now so once again it starts the same but then it's a little different here where the select wraps around the form control then it has a trigger and then we have the content that displays after it is triggered okay let's go back to the file tree now and find our way back to the customer form where we need to import our new select input here it is so with that let's just import it right here I'll say import and we want want select with label should come from components input select with label once again control B to hide the file tree alt Z to wrap any other lines down and when I look at these Imports here I can see since I added this one automatically as we did earlier with VSS code it put it at the bottom of the Imports but I'm just going to cut it with controll X put it underneath the select here so we have all of these Imports together here as the uh import or inputs all of the Imports of the inputs there we go a tongue twister so we have all of those together and that'll just be a little more organized okay when I come down here below we want to find city and then we would have state so this is where we would have our select input so we have select with label and this is also going to have the same schema we pass into it so we know everything else is Ty safe so we'll have Field title set this equal to State and now this is where the generic would check the name in the schema and I think it was lower case State and now we need to pass the data and we haven't imported that states array yet so we'll want to do that back at the top we can save that much and just right now we have a a lack of data I should say right there so let's import that states array up here we can do that with import States array and that should come from at constants and then SL States array so now we have our data let's copy that and we'll insert it here for the data prop and it looks good let's go back to our form in Chrome and check everything out it says we have a couple of Errors let's go ahead and refresh and see if everything's okay or if we still have those okay back in vs code I'm going to hold down control and click on select with label just to check out our component see if I did anything wrong here I easily could have as I scroll down I've got the form control and I instantly see the error we should have only had the form control wrapped around our trigger so let's put the closing tag after the closing select trigger and then the select content after that that is what we should have there so that is what I did wrong along the way now let's go back and once again look at our form see if we have gotten past any errors yep no more error here in the form let's check out our drop menu when I click on that we have got the full 50 states plus a lot of US territories in here and we should be able to select one let me select Kansas for example and yes it populates the field everything looks fairly good there let's go ahead fill out some data and then we'll have to look at everything say inside of the dev console and see if we're logging all of that data with our onsubmit function so I'll just put hands a city right here we've already got Kansas we'll go 1 2 3 4 5 put my email here 1 123-456-7890 and test message okay let me go ahead and open up Chrome Dev tools here with control shift and the letter I and now when we submit if I remember right we've already got a console log in there so when the onsubmit is called yes it logs the data over here and we can check everything out and we are getting all of that data as expected now this is a new customer so the ID is zero right now and that is fine we'll identify that as we submit to our server action but right now we just know we're getting the data from the form as expected let's go ahead and close that back out now what if their customer already existed let's try an edit form as we'd already set that up too so customer ID equals 2 press enter and yep the form is already populated as it loads so that's what we wanted as well everything looks good we've created all those inputs and we've completed the customer form except for the submission process to our server action and everything is type safe it gives us that information so if I delete Jane's name here and Tab out we get that immediate feedback that we do need a first name put Jane's name back tab out and everything is good so now let's apply these inputs to the ticket form and we're going to need one more and that's a checkbox hey I also want to quickly point out that when we had the new customer form and we hit reset it cleared everything but when we have edit Customer because of the way we populate the default values inside of our form if I delete Jane's name here and then I hit reset it brings Jane's name back because these are the default values that we set up as that data comes into the form okay let's get started on the ticket form back in vs code we can open up the file tree but I'm just going to click on the customer form that I have open up here above o scroll to the top at first and these inputs that we have here the input with label select with label and text area with label we're going to use all of those in the ticket form as well so let's go ahead and grab all of these and I can just copy them because we're using these Imports that start with the at symbol and so they work anywhere even if a file path would be different it knows where to grab everything from so we've got customer form customer form here so tickets form and then ticket form here so scroll up to the top and we'll make sure we've got all three of those inputs we've already created I'll press alt Z to wrap those down after that we'll scroll down to the form area and notice I've still got customer form up here so I can go back and forth between the two because I'm going to hide the file tree with contrl B again I'm going to scroll down to the form area we had we can go ahead and delete the stringify line here as we'll start creating our form let's go ahead and also just kind of model one form after the other where we're going to have columns just in case I had started out with a little bit different of class names there I'm going to come to the form here in the customer form copy this line that has my class names on the form put in the same class names just to match right here inside of our ticket form so now I have identical set up and I didn't type anything differently that way way we can also start our columns that way if we wanted so if we go back to the customer form remember this div indicated our first column and then I'll go ahead and copy this input label as well so right down here so our we'll start our column and we'll have a text input here our input with label copy both of those things paste those in here and then we'll close out that div so we will have started our first column save that now we don't have an ins insert customer schema type here in the ticket form do we we have a different one we have insert ticket schema type so I'll copy that come back down to our input paste in the correct schema there now you can see first name does not match this schema so we need to look at the inputs that we've set up up here above so we're going to have an ID customer ID whether we want to show all of these on the page or not is something else we also have title description completed and Tech we'll start with title so let's scroll down and get started on this input now so here we're going to have the title of the ticket and I'll just change this to match the actual schema so title that looks good let's have another input here and here let's go ahead and put an input with label for now and I say for now because in the next tutorial we're going to work on permissions and remember only managers and admins should be able to assign the tech to the ticket but for for now say anybody viewing this ticket would at least be able to see who was assigned so instead of a select here where a manager or an admin might use it let's use an input and let's just show the tech that is assigned and of course right now if I remember correctly all of the tickets we have in our database just say new ticket we have that new ticket email but we'll go ahead and display it at least and I'll put in Tech to match the schema there we go one other thing though because we have those props we can pass in a readon prop and we'll just set this equal to through now after this input is where I'd want to put the checkbox but we haven't created the checkbox yet so let's just go ahead and put everything else in the form and then we'll go create the check box so for now I'm going to put a div with a class name set a margin top equal to 4 and then a space- y-2 we have a little bit of space between what I'm going to put inside the div here we're just going to display the customer information it won't be in inputs it won't be anything that can be changed it's just who the ticket is assigned to because remember every ticket needs to start with a customer so here I'll have an H3 class name set this equal to text large and now inside of this we'll just put in customer info oh and it looks like it closed out that H3 here before I started the class name that looks better okay after that let's put in a horizontal rule I'll set the class name equal to a width of 4 fifths just four fifths of the div this one will be self-closing okay now let's put in a paragraph and inside of this will put in the customer oops we need all lowercase customer. first name let's put in a space and put in customer. last name on the next line put in customer. address one and then on the next line possibly an address to so let's think about how to handle that we could say let's use a turn are let's say customer do address 2 and if it exists well you know what we shouldn't start with the paragraph if we're going to do that let's display the paragraph if it exists then we'll display our customer address to and otherwise would be null okay after that now let's put in another paragraph and this would be our customer City we can put a comma and have customer State value and a space and the customer zip value again just all being displayed here on the form page for reference for who the ticket is for now let's put in another horizontal rule class name equals a width of 4 fifths just like we had above so I could have copied that after that we'll have another one that has the email so here's another paragraph customer. email and as you might guess we would have a customer phone so let's put this in in here I'll put in phone and we'll say customer own okay that looks good for our first column remembering that we still want a checkbox here at some point and we can quickly finish the second column let's go ahead and copy the beginning div once again so they're equal come down here to where the second column would start we get the closing div immediately now we're going to have two things in this a text area and then our area with the buttons so let's go back to the customer form scroll down in the customer form here was a text area with label so we can copy that from line 110 to 114 contrl C go back to our ticket form paste in our text area and think about what will be different here well we have to put in the different schema type I'll change those out and then the Field title it won't be the same this is going to be a description of the ticket so we had description and this would be description all lowercase as well and that should match a name in the schema and it does let's make this taller I'll put in 96 let's Mouse over that and see how much that is that's 384 pixels so a nice tall area text area for the description of the ticket after that we're going to have really the same form buttons that we did in our customer form so let's go back grab this same area that we had here with the div Flex Gap 2 so select that entire div contrl C to copy back to our ticket form and now this is actually going to be inside this column we'll make sure we put it in the right place and there we should have it I'm going to delete a couple of extra lines here let's take a look so once I save it's formatted correctly it's a submit button we still have the default save with the save name here and then when we look at our reset button it is once again the same and passes in the default values as well when it is reset so that looks great let's look at our form and of course the only thing that's missing is the checkbox that would go here after the tech name so back in Chrome we need to be able to pull up the form though so instead of customers we're going to go to tickets and then we can say customer ID 2 and it would be a new ticket if we do that but we're going to at least have a customer assigned to it so this is what we would get we have a blank ticket title and a blank description both required and after that we have the new ticket example we can't change it it's not disabled though as far as the the color didn't change for the text here at all but it is read only so we didn't see a color change but we do see that we can't change this at the this point then we have the customer info right here to reference so that's basically what was expected I can reset that get rid of those messages as well we could type something in here like computer fixed and we could type something in over here and say uh won't work and everything is good that's all that's really needed or required to complete the form are those two Fields except we're going to have a completed checkbox as well but of course with a new ticket it would never actually be completed but let's look at an existing ticket as well so we have customer ID of two uh or let's we don't need the customer ID when we have the ticket ID because it will pull the customer in that's correct so ticket ID equals 4 there we go now we have a edit ticket number four and you can see this is already completed so we have the customer info p in the title and the description as well so this Tech field this is is going to get adjusted in the next lesson when we actually set up permissions also because right now it's a read only so everybody can read who it's assigned to but only an admin or manager would actually be able to make the assignment back in VSS code we could fix that readon color in a couple of ways before we move on to the checkbox one would be to pass in classes or the readon color the other would be to set up disabled instead of read only because we actually put in colors in our input with label definition if you remember I'll hold down control and click on that for the possibility of it being disabled so let's go ahead and roll with disabled for now and we'll look back at the form to see if it is changed colors for our input there and there you can see now the tech with the new ticket at example.com is now green and if I switch to the light theme it's now blue because those are the colors that we put in so let's go ahead and go with those for now so it makes them stand out just a little bit or you could decide to possibly change that color if you want to do that you would go into the input with label definition or you could overwrite it by passing in a different class as well which would also work okay let's go back and create that checkbox now back in vs code once again I'm going to click on the file tree but I also have the input with label up here and either way you get there you just want to get to that inputs directory and we're going to create one more file in this directory so I'll create our new file here going to call this checkbox with label. TSX as we have with the other inputs we've created let's go back to that input with label file first also I'm going to press contrl B to hide the file tree so I can switch back and forth up here at the top and I'm going to copy the first 19 lines and just see what we need to change once again so everything through the props contrl C C to copy back into checkbox with label control V to paste as I scroll up we still have the used client directive going to use form context we're going to need all of the different form inputs and once again here is where things change so we don't need input or input HTML attributes we do need import and then we want checkbox and that's going to come from at/ components SL ui/ checkbox okay then we've got the checkbox to work with and we can start in on the props we'll go ahead and delete this input HTML attributes going to have a Field title we're going to have the name and schema that uses the generic so we can pass in the schema and instead of a class name here we're going to have a message and it's not going to be optional so let's go ahead and remove the optional part of that so a message that is a string and that's what we'll go with now let's go ahead and create the function I'm going to once again do that same thing where I copy the function as well and make some changes because it's that same type of form input layout we have seen in these other inputs so now paste in the function itself and we're going to call this checkbox with label and then we're going to have the Field title that matches the name and schema that matches no class name no props being passed in but we will have a message prop right here after that props with the schema that is all the same the form uses the form context and we start into the return for the form field it's going to once again use a form control it's going to use the name in the schema and start the render method and at the render method Things become just a little different because this is a checkbox and the label is not going to be above it it's going to be to the side all in one line here so let's add some classes that will help with all of this whoa I typed totally different things than I intended to I want class name right here going to set this equal to width full flex and then items D Center g-2 okay now for the form label I'm going to have text base but then I'm also going to have width D 1/3 and a margin top of two to HTML form name and schema that's the same Field title is the same now we come down to the form control and I'm going to wrap this form control in a div I'll put some classes on this div so we'll set this equal to class names Flex Flex Dash oops sorry not Flex Dash it's going to be items Das Center and GAP -2 I'll put closing div after the form control and we're also going to have our message so whatever message is passed in will go right here now let's look at the form control itself it's not going to be this input it's going to be a checkbox now that checkbox is still going to have the ID with name in schema we're not going to have any of these class names on it at all so we can eliminate at those we're not passing any props here but we will have field props passed from react hook form now this is different because once again much like the select this is a custom check box from Shad CN so it has oncheck change and we'll set this equal to the field onchange from react hook form after that we should be good I think yep we've got everything we need and that is the complete check box input so we're ready now to put that inside of our ticket form you can go back to the file tree to find the ticket form but if I close the file tree I've got mine right up here at the top so either way you want to navigate back to your ticket form and we want to put that checkbox in the first thing we need to do is import it up here at the top I'm going to import checkbox with label while I'm up here note that we haven't used the select label yet select with label yet on the ticket form and we won't until the next lesson because that's where we will be able to select different texts if we're a manager or admin as far as those permissions go okay now as we scroll down just want to find where we want to put that checkbox and it comes before the customer info and after the tech so here's where we'll have our checkbox with label and now it should have well it should also have I almost ski that every time we need to pass the schema as well now on the next line we're going to select or set the Field title and you know what instead of a Field title that's passed in we're just going to set this to completed then we could say name in schema this would be the name schema and after that we're going to have a message and we're going to pass in yes oh and here I'm thinking like two different things here is not where we have the name and schema prop this is where we' actually match what's above so yep it's getting to be a little bit of a long tutorial and I need to clear up my thinking so as we save that check boox with label now we have the Field title completed it's going to be a checkbox it matches our schema that says completed and beside the check boox it's going to say yes so we know to check the check box if yes it is completed okay with that let's go ahead and take a look at our ticket form once again and here is our checkbox field it's completed we can check it or uncheck it and everything should be working as expected there as well so let's go ahead quickly look at the dev tools again I'll clear out the console here let's check it as if it was completed we have screen replacement description and everything else here the text so let's save see what we get over here so we have completed is true so this is a Boolean we get true or false that matches our schema the customer ID the description and everything else as expected in the form now if we reset this everything is basically back to the way it was I noticed that our completed did not reset we may need to fix that okay so back in vs code to fix our checkbox we want to hold down the control button and click on checkbox with label which should take us to that file so you could just open that file either way that you want to get there once we're there we just missed adding one field here after the field that is spread in and before oncheck changed we need to just put checked and set that equal to field I could spell value and this will keep it checked or unchecked so let's go ahead and save that and now let's go back to the browser and check out our field once again so I'm going to reload the page just to make sure everything loads in as expected okay with the page now loaded let's go ahead and check everything out if we hit save right now you can see we have a false over here in our console window and now if we click the completed box and hit save it is true so that's good let's clean this out once again and now let's hit reset and it does uncheck as expected now let's hit save to make sure it once again says false yep everything's working as we want it to so we've pretty much completed our ticket and our customer forms we just need to come back in the next tutorial and address the permissions so tickets can be assigned to individual texts that are users in our a a quick shout out to my patrons holy coder is a progress provider Sean Lynch is a senior Patron and my junior patrons programming polyot Isaac will Ernie Stacy Abe Javier Michael thank you all so very much you're helping me reach my goals remember to keep striving for Progress over Perfection and a little progress every day will go a very long way please give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon