
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 In order to be able to show real companions on the homepage and the companions library, we need to store them in some database.
00:00:09 But before that, we need a form that allows us to submit those companions.
00:00:15 And forms can be tricky at first.
00:00:18 But thankfully, ChatCN paired with React Hook Form will do the heavy lifting for us.
00:00:23 So, head over to React Hook Form within ChatCN UI, and let's install our form.
00:00:28 Right within our code, I will head over to the terminal and run mpx-chatcn-add-latest-add-form.
00:00:36 And I'll use the legacy peer depths as usual.
00:00:39 And then we can create a new component called companion-form.tsx.
00:00:46 I'll then run RAFCE.
00:00:48 And we'll need to import this form right within our page where we want to create new companions.
00:00:54 That's within app, companions, new, page.tsx.
00:00:58 So within here, let's turn this into a main, since that's the main part of the component or the page.
00:01:04 Let's render an article between it.
00:01:07 And let's render an h1 that'll say companion builder.
00:01:12 And right below it, we can render a companion form.
00:01:17 There we go.
00:01:18 Now we can explore this in action by clicking build a new companion right here.
00:01:24 And you can see companion builder and then a companion form right below it.
00:01:29 We can style the layout a bit more by giving this main tag a class name equal to min-lg, w of 1 over 3. On min-medium devices,
00:01:41 the form will take two-thirds of the view, and it'll always be centered both vertically and horizontally.
00:01:51 There we go.
00:01:52 This article will have a class name equal to w-fool, a gap of four, flex and flex-call.
00:02:02 And now we can head over into the companion form.
00:02:04 Here, I'll start by copying the usage from React Hook forms, or rather let's do it step by step.
00:02:11 I'll first copy the step one, which is to create a form schema.
00:02:16 I'll zoom it out so we can see a bit better.
00:02:18 So first, we have to define the schema of our form using a Xaad schema.
00:02:24 You can read more about it in Xaad documentation, but don't worry as I'll explain everything as we go.
00:02:30 First things first, we have to turn this into a client rendered component or page because we are dealing with browser functionalities such as keyboard
00:02:39 events and form submissions.
00:02:41 We then import Z from ZOD, which will allow us to validate the inputs within our form.
00:02:47 Next, we have to define the form itself.
00:02:50 So we have to import two more things, which is going to be the ZOD resolver, as well as the used form.
00:02:56 And then, within our form, we have to do two things.
00:03:00 First, we have to define our form, and then we have to submit it.
00:03:04 So copy this part and add it at the top of your companion form component.
00:03:09 You'll notice that this form requires some kind of a form schema, which for now only accepts a username.
00:03:16 So we need to modify it to suit what our form needs.
00:03:20 For example, it'll need a name, which can be a z.string.min one character.
00:03:27 We don't need the max, but I will add a message.
00:03:31 In case this rule is not met, for example, companion is required.
00:03:37 And we can duplicate this a couple of times.
00:03:39 For the second one, I'll say subject and subject is required.
00:03:44 We'll also need a topic.
00:03:47 And topic will be required as well.
00:03:50 After that, we'll need a voice that we're going to use for the lesson.
00:03:54 So it has to be required.
00:03:56 We'll also use a style of the conversation.
00:03:59 So we'll say style is required as well.
00:04:03 And finally, a duration.
00:04:05 Now, duration has to be a number, so I'll say z.coerce.number with a minimum value of 1, and then we can say duration is required.
00:04:17 So now that we have this form schema, you can see that we're actually using it to define our form.
00:04:23 And therefore, we have to also choose the default values of that form to match the form schema.
00:04:30 To do it quickly, I will hold the option key and select all of these different keywords and I'll paste them right here.
00:04:38 Then I'll do some more keyboard shortcut magic by holding the option key to create multiple cursors.
00:04:44 And then I'll set all of them to an empty string besides the duration, which I will set to be equal to about 15 minutes by default.
00:04:52 Now that we have our form, we also need to define a submit handler or what will happen once we submit the form.
00:04:59 I prefer arrow functions, so let's actually turn this into a const on submit as an arrow function.
00:05:06 And for now, we can simply const log the values once we submit the form.
00:05:10 We can then move over to the step three, which is to build our form.
00:05:15 And we can build it by copying all of the different components that will make up the form.
00:05:21 So I'll paste them right here at the top.
00:05:23 Now we have already installed the form as a ShadCN component, but we haven't yet installed the input.
00:05:29 So head over to the terminal and run mpx shadcn add latest.
00:05:35 Add input and we can also add a text area.
00:05:39 Once you add those, we can head below and I'll copy this part where we actually rendered the form instead of this empty div right here.
00:05:48 You'll notice that it'll complain a bit saying that the name is equal to username.
00:05:54 But in this case, name can be just name because that's what we have under our default values.
00:05:58 So with that in mind, it looks like our form is done.
00:06:02 You now have a fully accessible form that is type safe with client-side validation.
00:06:08 So if I click submit, you can see that it actually gives us an error.
00:06:11 And if I go back to our application, if I click submit, we have the same thing, but now we have to render the actual inputs that our specific form needs.
00:06:20 The first form field is already almost as good as it is, but I'll change the label to something like companion name and I'll give it a placeholder of enter
00:06:31 the companion name.
00:06:34 with a class name equal to input.
00:06:37 I'll put it in a few lines, just so it's a bit easier to see.
00:06:41 And in this case, we don't need the form description, but I will leave the form message so we can display it if something goes wrong.
00:06:47 Now, we can duplicate this form field just below, and I'll actually do it a couple of times for each one of these different fields.
00:06:55 So that is one, two, three, four, five times more.
00:07:00 Let's do it once, two times, three times, four times, and five.
00:07:06 There we go.
00:07:07 So now we have a lot of different fields.
00:07:09 So let's head over to our second one and I'll rename it to subject.
00:07:15 The form label will be subject as well.
00:07:18 And in this case, instead of simply rendering an input, we want to render a select component.
00:07:24 So in this case, I will open up our terminal and run mpx-shadzian-add-latest, add select.
00:07:33 We'll use legacy pure depths.
00:07:36 And now we can render a select right within it.
00:07:39 So let's copy it right here and paste it within the form control.
00:07:44 And with that, it is already looking good and it seems to be functional, but we're going to modify it for our needs.
00:07:51 We have to control the value that has been selected.
00:07:54 So within the select, I'll say onValueChange is equal to field.onChange, value will be equal to field.value, and the default value will be set to field.value.
00:08:10 React Hookform makes it super easy because we're controlling everything using this field prop under the form field renderer.
00:08:17 Next, we can give this select trigger a class name of input and capitalize.
00:08:24 And we can give a select value, a placeholder of select the subject.
00:08:31 There we go.
00:08:32 And now under select content, I will remove the three dummy select items.
00:08:37 And instead I will map over the subjects coming from constants.
00:08:43 And for each one of these subjects, we want to automatically return a select item.
00:08:49 Each select item will have a value.
00:08:54 And that value will be equal to subject.
00:08:57 It'll have a key since we're mapping over it, also equal to subject and a class name of capitalize.
00:09:04 And within the select item, we will render the subject name.
00:09:10 So if you have done this properly, you should be able to see all of the different subjects that we're offering within our application.
00:09:17 Later on, I'll show you how we can modify these, but for now, this is more than enough.
00:09:21 And that's it.
00:09:22 We have our second input.
00:09:24 I will just reload the page so we don't have to stare at these errors.
00:09:27 We have the companion name and the subject.
00:09:30 Now let's head over for our third one, which is going to be the topic.
00:09:35 So under the form label, we can say, what should the companion help with?
00:09:42 And then for the placeholder, we can give it an example, like ex, derivatives, and integrals, for example, if we're dealing with some heavy math problems.
00:09:54 And that's it.
00:09:55 But instead of it being an input, we can make it a text area.
00:10:00 So text area.
00:10:01 which will give the user a bit more space to explain what they want.
00:10:05 Next, we can head below, and we're going to have another Select.
00:10:09 So actually, I want to delete this Form field that I entered before, and I want to duplicate the Select one that we have already created.
00:10:18 So I'll copy the select field and paste it right here as the fourth field, but we'll want to modify it just a tiny bit.
00:10:26 This one I'll call voice and the label will say voice as well.
00:10:31 We're going to keep everything the same, but within the select trigger, we'll give it just an input and a placeholder of select the voice.
00:10:40 That'll look something like this.
00:10:42 And then for the select contents, we're going to display two different select items.
00:10:47 One that'll have a value equal to male and it'll render a text of male.
00:10:53 And the other one, which I think you can guess, will render a value of female and also the text of female right here that allow us to choose the type of
00:11:04 the voice that we want our learning companion to have.
00:11:08 Now I will duplicate it one more time below it.
00:11:11 And this time, I'll ask for the style of the voice.
00:11:16 So we can change this to style, the form label to style as well.
00:11:21 We'll keep this the same.
00:11:22 The trigger will say select the style.
00:11:24 And then for the select contents, instead of male and female, we'll say formal.
00:11:31 Formal here as well.
00:11:33 And informal, or in this case, we can say casual.
00:11:36 So now we have two different selects, one for the male or female type, and one for the style.
00:11:42 And finally, just below the style, we want to have one more form field.
00:11:47 I think we currently have two, so I'll delete one.
00:11:50 And the last one I'll rename to duration.
00:11:54 And the label will also be set to estimated session duration in minutes.
00:12:00 This time, it'll be an input with a placeholder of something like 15, a type of number so that the users can more easily select the number of minutes they
00:12:12 have with these plus and minus signs.
00:12:14 And I think that's more or less it.
00:12:16 We can finish it off with a button that has a type of submit.
00:12:20 And to make it a bit more apparent, I'll give it a class name equal to WFool and cursor-pointer.
00:12:28 And instead of making it say submit, I'll make it say, build your companion.
00:12:35 There we go.
00:12:36 So now we have a full companion builder form.
00:12:40 At least the UI here, and on full screen, it should look something like this.
00:12:44 And if you try to submit it, you'll notice that we have different errors saying that the fields are required.
00:12:50 But if you try to successfully submit it, such as entering a real companion name, Let's do something like maths in this case,
00:12:58 and we need help with let's say multiplication.
00:13:01 Choose the voice, style, and the estimated session duration and click build your companion.
00:13:07 If you do that and open up inspect element and head over to console, you'll see that we'll get back an object with the values that we have submitted.
00:13:18 Duration, name, style, subject, topic, and voice all right here at our disposal to do something with them.
00:13:25 Where are we getting those from?
00:13:27 Well, from the function submit function right here.
00:13:31 Later on, instead of just console logging them, we'll do something useful with them.
00:13:35 But now, to be able to submit our actual tutor, we need one more very important component.
00:13:42 And that is the user that is trying to create their companion, because otherwise, how are we going to know which companion belongs to which user and how
00:13:52 many they have created?
00:13:53 To do that, we need to implement authentication.
00:13:56 So far, the UI is looking great and very soon we'll actually be able to create companions, but hey, we cannot do it if we cannot create our own user yet.
00:14:08 So let's do that next.