New Events Form
Create a form to allow users to create new events and display them in a table.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Sleek Next.JS Applications with shadcn/ui course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Sleek Next.JS Applications with shadcn/ui, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:10] In the previous lesson, you have designed a table sales and others and made it interactive. In this lesson, you will create a new table to display the events that the users registered for.
[00:11 - 00:21] You will also integrate your learnings from the previous lesson to create a new form that allow users to create new events. The form looks like this.
[00:22 - 00:31] Users will be able to define the event properties using the form, the title, description, image date and location. The image field requires a spatial treatment.
[00:32 - 00:42] You will need to allow the user to upload the image and preview it before submitting the form. The date field will be a date picker from Shadze and UI and the description will be a text area.
[00:43 - 00:50] The location and title will be a simple text input. Only logged in users can create new events, so you will need to add a check for that as well.
[00:51 - 01:05] The API offers a post, route for an event that receives the event details and creates them in the database. The MyVence table will show events the user is hosting and users will be able to create this event through the form.
[01:06 - 01:20] Let's create a new file. It app/events/myvents will be collocated with the registered events at the page and start by adding a use-gline directive on top.
[01:21 - 01:51] Unimport the user's WRUG, import the event type from types/events, defature function, the events table and the use-user hook. Now create the MyVence component, export const, MyVenceEqualFunction, get the token and the user from the use-user hook.
[01:52 - 02:11] And make a network request using the user's WRUG the same way you did for the registered events component. Now the data object returned from the server will look like this, and objects with events property inside which is an array from the event type.
[02:12 - 02:30] And then we want to pass both the URL, the event route and we want to pass the user ID. And we need to pass the token as well.
[02:31 - 02:44] For the second argument, destructure the URL and token and call defature function. But we also want to pass the refresh interval to the use-user WRUG.
[02:45 - 03:07] So it will remake the request every second. And now we can simply return the events table that we already built and pass the events returned from the server into it.
[03:08 - 03:22] With the RanoEvents, we can pass an empty array. Now go back to the events page, import the MyVence component.
[03:23 - 03:37] And let's render it. We want to wrap the current component in the registered event section with a new deal, add a class name to it with Creed Gap16.
[03:38 - 03:52] And then add another div, similar to the registered event one. But instead of simply rendering the header, we need the header to include two components.
[03:53 - 04:00] So we are adding flex styles to it. And we want the MyVence Titan.
[04:01 - 04:09] And render the create event component, which we will create in a second. And beneath render the MyVence component that we've just created.
[04:10 - 04:24] Now import create event from dot/create event and create it. Let's build the create event form.
[04:25 - 04:35] We start by creating the form schema with Zod. The schema is an object.
[04:36 - 04:44] And the object receives the title, which is a string with a minimum length. So we'll make it required with a spatial error.
[04:45 - 05:09] Then we need the description property, which is optional. The location, the image property, which isn't required as well, and the date property, which is required.
[05:10 - 05:20] Now create the create event component. And let's import the use user hook.
[05:21 - 05:31] Ask for the user object from the hook, the structure, their response. And now we want to condition the render in case there is a user logged in.
[05:32 - 05:41] We want to render the create event pattern and dialog. And if not, we want to render the login button.
[05:42 - 05:52] We can pass a label to keep the user experience the same, login to create event . And if there is user, we want to render a dialog.
[05:53 - 06:04] So import the dialog component from ShadCNUI with the ease open property. And on open change, we want to change the ease open property.
[06:05 - 06:16] And we need to add a state to our component. So ease open and set ease open equals use state false.
[06:17 - 06:18] Let's import use state. Great.
[06:19 - 06:27] Now we need a dialog trigger. This is what the user will see initially.
[06:28 - 06:39] Don't forget to import the patterns. And then render a dialog content which will be shown to the user if the button is clicked.
[06:40 - 06:52] So inside of it, let's add a class name, max with 3xL and 0 padding. And render the create dialog component that you are going to create in a minute .
[06:53 - 07:05] On complete, when the user is completed to create the event, we want to close the dialog. Don't forget to import the dialog content.
[07:06 - 07:10] Great. Now it's time to create the create dialog component.
[07:11 - 07:21] Export const create dialog with full of function. And add a non-complete prop to it.
[07:22 - 07:29] It's a function that receives nothing and returns void. She's also returning nothing.
[07:30 - 07:37] Now we can initiate the form using the use form hook form react hook form. Let's pass the type to it.
[07:38 - 07:54] We can use the z-zod in fair type based on the form schema. And we need to pass the resolver the same way we did for the authentication form.
[07:55 - 08:01] With the form schema, we already created. We can pass default values.
[08:02 - 08:18] Title, location, description, image. And for the date, you want to pass an actual date object, which will be equal to the current time of the user.
[08:19 - 08:24] Don't forget to pass an object and close it. Great.
[08:25 - 08:30] You've now initiated the form object. Let's create the handler, the unsubmit handler.
[08:31 - 08:47] She's an asking function that receives values from the form schema type. And make a request to the server.
[08:48 - 08:57] We're using the native fetch function. First, the slash event route.
[08:58 - 09:07] It should be from the post method. We should pass a stringified JSON of the values in the body.
[09:08 - 09:27] And for the others, you need to pass the authorization token. Let's grab the token from the user hook.
[09:28 - 09:42] Now tone request into a JSON. And if there is no event on the response from the server and there is a message , that means that there was an error.
[09:43 - 09:54] We should now set the form error on the root level to be the server message. Then if that's the case, we want to early return.
[09:55 - 09:59] And if not, we can call the uncomplete function. The second handler we need is for the image upload.
[10:00 - 10:11] So we create an on-image-appload function. It receives an event property from the React type and an HTML input element.
[10:12 - 10:31] Then grab the file from the event target, which is the input. If there is file, we want to create a new file reader object.
[10:32 - 10:51] She's a native browser API. Then we want to define the own load and set manually the form value of the image to equal the reader result string, the clarity as a string.
[10:52 - 11:02] And then we need to call the reader dot reader's data URL. We will send the string to the server and it will know how to handle this and upload it to his own hosting.
[11:03 - 11:08] Let's add an optional dot here. Now we are ready to render the form.
[11:09 - 11:30] We want to return a card with full width and without any border, the card header and the card title, which is create event. Let's set a description as well for the user.
[11:31 - 11:46] Anyone will be able to join your events. Now render the card content and the same way that you did for the authentication form.
[11:47 - 12:03] Render the form function from Shadze anyway, which is a wrapper around the React to form provider and spread the form object inside. Now render an HTML form tag and pass the on-submit function into it.
[12:04 - 12:13] Read with a form and the submit of the React to form object and the on-submit function that we defined. And let's style that.
[12:14 - 12:33] So flex, flex call reverse item start, gap 8, md grid and md grid calls to. This will create a two column layout on the stop sizes and the one roll layout for mobile.
[12:34 - 12:46] Let's create the inside of the form. The first part is the non-image inputs, so full width, grid, flex one, gap syn cs.
[12:47 - 13:16] And we want to start create the fields. The first field will be the title, so render a form field, pass a control, pop into it, pass it a name and a render function that receives the field property in its pop and render a form item, a form label for the styles, which is the title and the form control which will include the input.
[13:17 - 13:29] Let the place older, event item and spread the field property inside. Right, now we want to render the date form field.
[13:30 - 13:47] So, pass the control, pop, add a name date. And on this case we are going to handle the input and the values manually.
[13:48 - 13:59] Start with the form item, then a form label, add a class name to it because we are going to render an icon as well. Render the calendar icon.
[14:00 - 14:11] Give it the size 4, class name and a text mute to the foreground. And then render a date string inside the span.
[14:12 - 14:18] And then render the form control. Now we are going to use ShadCNUI, date picker.
[14:19 - 14:30] The date picker component is composed from three different other components, the popover, the button and the calendar. Let's install the more VR ShadCNUI CLI.
[14:31 - 14:45] And pick ShadCNUI at latest, add popover and calendar, the button should be already installed. We run the app and the date picker is installed by copying a pasting its implementation.
[14:46 - 14:54] So you can find it on the course text below, I'm going to copy and paste it here. Create a new file inside components called date picker.
[14:55 - 15:05] And paste its content. You can see if you look at the date picker that it receives a date value, which is the date object, and an on-change function which also receives date object as a problem.
[15:06 - 15:19] It will then render a popover and a popover trigger with a button inside that will either show the value or the pick a date placeholder. And then once the user click on the popover, it will render a calendar.
[15:20 - 15:34] On select for any day, it will call the on-change function. So let's render it inside our form control.
[15:35 - 15:43] And render the date picker inside. Past the value, which is the new date field of value.
[15:44 - 16:06] And on-change, get the date property as a param and call the form.setValues.set Value with date and turn the date into an isoString. Let's render the location field.
[16:07 - 16:23] She's a simple input. Render form item.
[16:24 - 16:47] And then a form label with the same class name for the date input. And then render the map in icon with the size for a class name and text-muted foreground.
[16:48 - 16:58] And render the location text inside the span. Now render a form control.
[16:59 - 17:02] With a simple input inside. Let's add some styles to it.
[17:03 - 17:12] With full just if I start. Text left.
[17:13 - 17:19] And font normal. Past the placeholder, which is the event location text.
[17:20 - 17:33] And spread the field. Close the field.
[17:34 - 17:40] And now render the description field. Here we are going to use the text area component from ShadCNU1.
[17:41 - 18:14] We're going to install it in a minute. And render the form control.
[18:15 - 18:23] And render the form message as well. We need to add the form message to the other components as well as I forgot to add them.
[18:24 - 18:32] And they will show the arrow as we've seen in the authentication form. Here they're mandered the form control property.
[18:33 - 18:41] Now what we need is the submit button. Add a with full class name to it.
[18:42 - 18:48] Type submit. And add a disabled rock as we did in the authentication form.
[18:49 - 18:55] When the user is submitting, we want the button to be disabled. Add a simple submit text.
[18:56 - 19:00] And that's the first part of the form. We're going to add now the image field.
[19:01 - 19:08] Like the date field, we are also going to need to handle the input menu earlier . Render a new form field component.
[19:09 - 19:16] Past the control property to it. Name equal image.
[19:17 - 19:22] And call the render function. We're going to add a full item as well.
[19:23 - 19:37] And this time we'll see a bit more styled class name. Render a div to wrap the old section.
[19:38 - 19:48] We will make it a drag and drop area with full and bg background. And render the form control.
[19:49 - 20:01] Now we are going to render the aspect ratio to keep the old area to its ratio. We can skip passing a prop because we want the 16 divided by 9 ratio.
[20:02 - 20:15] Inside the aspect ratio component, inside the aspect ratio, we're going to condition the redener either an image or an input. The input will allow users to either drag and drop or choose images.
[20:16 - 20:42] So let's check if there is an image. And if there is one, render the image from next GS with a field property and a class name of object cover, md_rounder_pulperty, passes souls, and an alt which is equal to the title of the event.
[20:43 - 21:05] And if there is no image, we want to render a label with hml form property and a cursor pointer class name. Now render a div which will be the style container for the area, the drag and drop area.
[21:06 - 21:24] Add a border, dashed border, and add some background. Now we are going to render the upload icon inside with a size 6 class name and a text muted foreground as well.
[21:25 - 21:42] Then we want to render the muted component with upload image text. And then a hidden input should have an ID image so the label will be wrapping that and now how to end this day input and then file type.
[21:43 - 21:52] Make the class name hidden, we want to show the actual input to the user. And add a non-change function which will call our own image upload handler.
[21:53 - 21:58] Then only accept image files. Perfect.
[21:59 - 22:03] The firm should now be ready. Let's check if it works.
[22:04 - 22:17] Go to the My Events page, make sure your app is running, and click on Create Event. This is the firm design you can see that it's pretty much the same.
[22:18 - 22:28] Let's add a new event. Upload an image.
[22:29 - 22:44] You can now see the image preview and call the Submit function. You can now see that the button is disabled once I'm submitting the form.
[22:45 - 22:48] The event is now created and added to the table. That's it.
[22:49 - 22:52] In the next lesson, you will add pagination and sorting to both tables.