
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.
Complete source code for this lesson is available at
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 Let's show a list of top technologies that this user has something to do with.
00:00:07 Either they were posting questions in that category, or they were showing their expertise by answering some questions within that tag.
00:00:15 We'll start by implementing the logic that gets the user stop tags.
00:00:19 It won't be as straightforward as currently we're not associating the user with any tags.
00:00:24 Tags are independent and can be created on the fly, not by anyone specifically.
00:00:29 So we'll have to approach this by finding all the questions created by the users and then grouping them by their associated tags.
00:00:37 From there, we'll find out which tags are more commonly used in each one of these questions and then return them.
00:00:44 Before we start implementing it, let's first head over into the action.d.ts and let's define the params.
00:00:52 I'll just create a new interface and say get user tags params.
00:00:59 And I'll make it equal to just get the user ID.
00:01:05 Now that I'm looking at it, we could have created one interface if it's the same, and then call it something like getUserDetails that has the user ID.
00:01:13 But it's okay.
00:01:14 We can also head over to validations and just replicate whatever we have so far.
00:01:21 Export const getUserTags schema, which is equal to Now we can head over into the user.action.ts.
00:01:37 I'll go ahead and duplicate the get answers that we had right here by copying them and then pasting them below, but we'll have to make some changes.
00:01:47 Instead of calling it getUser'sAnswers, I'll call it getUserTopTags.
00:01:54 And here I'll say getUserTags params will return a list of tags.
00:02:03 which are basically an object that has an underscore ID of a type string, a name of a type string as well, and finally a count of how many questions belong
00:02:14 to that tag, and will return an array of those tags.
00:02:18 In this case, we won't paginate it, so we don't need to have the isNext property.
00:02:22 First things first, we're passing some params and then we're checking for the errors.
00:02:27 After that, the only thing we get back is the user ID.
00:02:31 In this case, we will not have any kind of pagination, so I can remove everything regarding skip, isNext, limit, and so on.
00:02:40 and we'll just deal with what we are returning.
00:02:43 So let's clear up the entire tri-block and let me show you how we'll get access to all of the tags that the users have interacted with.
00:02:52 Once again, we'll have to form a MongoDB pipeline.
00:02:55 So I'll say pipeline is of a type pipeline stage coming from Mongoose, actually an array of those stages.
00:03:05 First things first, we'll have to match the questions this user has something to do with, or that they are the author of.
00:03:13 So let's say match where the author is equal to new types coming from mongoose.objectId of the user ID.
00:03:26 So give me the questions that match this author, then flatten the tags in that array by saying unwind$tags, then group them together by the number of occurrences.
00:03:42 We can do that by using the group property.
00:03:45 where we'll group them by the underscore ID of the tags.
00:03:50 And for each one, we'll increase the count by one.
00:03:53 Then we want to lookup like this, dollar sign lookup from tags where the local field is underscore ID, a foreign field is underscore ID as tag info.
00:04:06 We once again want to unwind that tag info.
00:04:11 Bear with me, I know this is getting a bit complicated.
00:04:14 So I'll say dollar sign tag info.
00:04:18 And we want to sort it by the number of occurrences.
00:04:21 So I'll say dollar sign sort where the count is minus one.
00:04:28 like this.
00:04:29 Finally, we will limit it to only give us the top 10. So I'll say dollar sign limit will be set to 10. And finally, we only want the output to include
00:04:39 the relevant fields.
00:04:40 We don't need to get anything out of it.
00:04:42 So I'll say project the underscore ID, which will be a dollar sign tag info dot underscore ID, a name, which will be a dollar sign tag info dot name,
00:04:54 as well as a count of one.
00:04:57 And this has to be within strings, so tagInfo.id as well as tagInfo.name.
00:05:05 And here we have created a list of pipeline stages that we can aggregate and execute to be able to get the tags that belong to a specific user.
00:05:16 So let's say const tags is equal to await.
00:05:20 question.aggregate, and we want to pass over the pipeline we created.
00:05:25 And finally, we want to return a success of true and tags where we can parse them and stringify them.
00:05:33 Great.
00:05:34 So let's get access to those within the profile details page by heading over to profile ID.
00:05:41 And I'll get access to them right at the top in the same way that we call the answers and questions.
00:05:48 So once again, I will duplicate this and I'll call it user top tags success.
00:05:55 Data will be user top tags.
00:06:00 And the error will be, I think you can guess it, user top tags.
00:06:06 Error.
00:06:06 Into it, we don't want to paginate it.
00:06:08 We just want to pass the user ID.
00:06:10 And we can now destructure the data out of it.
00:06:13 So I'll simply destructure the tags out of the user top tags.
00:06:22 Now, hear me out.
00:06:24 I do understand that this file is getting long.
00:06:28 We have about 200 lines for the profile page and we have many different calls happening right here at the top.
00:06:37 In my YouTube videos, I try to teach you to keep your files clean and simple to understand.
00:06:44 Just some simple logic at the top, and then below, some JSX.
00:06:48 But here, we're getting to the reality of how things are.
00:06:51 And that is that when you're creating complex applications, inside of which you want to fetch multiple pieces of data, have some kind of a tab array layout
00:07:01 that shows different pieces of data, and show even more data right here, things are going to get messy.
00:07:08 And your code will not be super simple to understand, but if you follow nice structured practices, such as using the server actions we have created,
00:07:18 using proper naming practices, it'll still be maintainable.
00:07:22 Let's put it that way, okay?
00:07:24 So even though it might feel a bit complicated right now, as we have a lot of things going on, Don't worry about it at all.
00:07:31 Once you go through it a couple of times and once you get used to working with larger files and heck, larger code bases,
00:07:39 this code base is becoming very large.
00:07:42 It'll all start making sense and you'll find yourself at home traversing this huge of a code base.
00:07:49 Right now, if you're not there yet, don't worry about it at all.
00:07:53 I've been there too.
00:07:54 I used to struggle with code bases that have more than 10, 20, 30 files and each file leads somewhere else.
00:08:01 You struggle finding yourself around here.
00:08:04 And what does all of this mean?
00:08:06 But if you follow best practices, if you understand how this is working behind the scenes, trust me, with time, it'll all make sense.
00:08:16 If you need to take a pen and paper or some kind of a drawing tool like draw.io online to draw out a diagram of how we're fetching data from a server action,
00:08:28 how we're then calling it within this profile details page, how we're destructuring data and then displaying it, take some time,
00:08:35 pause, go through the code base a bit and try to understand it.
00:08:39 I know it's not super simple, but with time and effort, it'll start making sense.
00:08:46 Great.
00:08:47 So with that said, we now have access to these tags.
00:08:51 I will, for one last time, duplicate this data renderer and I'll paste it right here below the tabs where we have this div h3 and then another div.
00:09:06 And within this div, I will now paste that data renderer.
00:09:11 I'll change the data to tags.
00:09:14 I'll change this to empty tags.
00:09:18 I'll change the success to user top tags success and the error to user top tags error.
00:09:27 We're rendering through tags.
00:09:29 For each tag, we'll display a div with a margin top of three, flex w-full, influx-call with a gap of four, and we'll map over those tags.
00:09:45 And for each one of the tags, we will display a tag card.
00:09:51 Thank God we have already created that card before, so we can simply use it right here.
00:09:56 By passing over a key equal to tag.underscoreID.
00:10:01 passing over the underscore ID itself, equal to tag.underscoreID.
00:10:06 We can pass the name of the tag, which will be equal to tag.name.
00:10:11 The number of questions associated with that tag, so that is the tag.count.
00:10:17 We can also pass over the show count, as well as the compact, because we want to show the compact version of this tag.
00:10:27 Here we can also say that the tag is of a type tag.
00:10:31 And you can see that here, Tabscript doesn't know what this tag is.
00:10:35 And that's because when I was trying to destructure the tags, it actually says that the user top tags don't exist because,
00:10:41 hey, I forgot to call the right server action.
00:10:44 So here I'll say get user top tags.
00:10:49 And with that, we have no problems with the props.
00:10:52 And check this out.
00:10:54 We see the top tech that this user has interacted with, and they have interacted with Next.js, JavaScript, and React.
00:11:01 This is amazing.
00:11:03 So now we know what this user is all about.
00:11:05 What kind of tech are they into?
00:11:08 And just how powerful our app is becoming, now we can go from the profile page to something like a question page, or to the answer page,
00:11:17 or we can even go to the tag page, just by clicking on the tab right here, so we can explore what other users are talking about that specific technology.
00:11:27 This is working great.
00:11:28 On tablet mode, we can still see the top tech, but on mobile mode, the tags are gone and we're only showing the answers and posts.
00:11:38 This is beautiful.
00:11:39 And with that, our profile page has been completed as well.
00:11:43 Our app is growing every second and it feels more like a full stack enterprise ready application that people will actually use day to day to get the answers
00:11:55 to their coding questions.
00:11:56 I know this was a tough one.
00:11:57 We implemented many different server action calls within the same page.
00:12:02 But as I said, with time, it'll all start making sense.
00:12:06 Even though right now you might be a bit confused, that is totally normal.
00:12:11 Give it some time to let it process.
00:12:14 You'll get back to it and it'll all start making sense.
00:12:17 So let's go ahead and commit this by saying something like implement user tags, commit and sync.
00:12:27 And that brings us to the end of the profile page module.
00:12:31 What's coming up next?