So now that we have implemented our following system, I want to create a little sidebar here similar to recommended, which is going to show the followed users. And also when we follow a user, we want to remove that user from the recommended users, right? Because they're already following that user, so no point in recommending them. So what I'm gonna do is I'm just gonna run npm run dev because I shut it down. So npm run dev and in my other terminals, I'm not gonna run anything.
So I don't have anything running besides npm run dev no need for ngrok or any local tunnel because we already added our users so just make sure that you have at least two users in your database So I'm logged in as you can see, whoops, I'm logged in here with a user called Antonio and in here in my sidebar I have another user. So just make sure you have at least two users so you can actually see the effect of what we are going to build. So the first thing I want to do is I want to go back inside of my lib and inside of the follow service right here. And in here I want to create a function which is going to get me all of the users that I am following. So I'm going to do that at the top here.
Export const getFollowedUsers is going to be an asynchronous function. And first thing I'm going to do is I'm going to open a try and catch block. And in the catch, I'm just going to return an empty array because if a logged out user tries to do this it's going to immediately fail because the first thing we do is we attempt to get the currently logged in user. So this will throw an error for users that are not logged in. As you can see right here, we throw that error if we don't have the user.
And in that case, we're just gonna return an empty array, meaning you're not following anyone because you're not logged in. But for logged in users, we're gonna do the following. We're going to return db.follow.findMany where the follower ID is self.id like that. And we're also going to include following true. So we have the information about that user and let's actually put this in a constant first so followed users and then let's go ahead and return followed users like this.
There we go. So we have our very simple function which goes through the database and looks at all the users which have a matching follower id of the currently logged in user meaning that it's followed by that user and we also include information about the user that we are following so we can display them nicely inside of our sidebar. So just make sure you added this small little util here and what I want to do now is I want to go inside of my app folder, browse components, sidebar, index and alongside get recommended I'm also going to add follows. So await getFollowedUsers like that. So make sure you import getFollowedUsers from the follow service and make sure you have the recommended service here.
And now we're going to do a very similar thing here. So in here, I'm going to create following and pass in the data to be follows like that. And Perhaps we can call this following as well. It seems to be matching. So let's rename this constant to following and this to following as well.
Great. Now we have to create this following component. So let's go inside of the sidebar and create following.tsx like that. And I'm going to mark this as use client and export const following very quickly and just return a div saying following and now you can go back to index dot TSX and you can import following from .slash following the same way we did with these other ones. So I'm just going to go ahead and align those now.
I will move this to the top because I like my imports in that way. Great. And let me just collapse this elements like that so we have toggle and toggle skeleton and we have this great so now let's go back inside of the following and first thing we have to do is resolve this typescript error because currently it cannot accept this type of data So let's create an interface following props to accept data, which is gonna be a type of follow, which we can get from Prisma Client because we run npx Prisma generate, but we also include something in there and we include the following property which is our user from prisma client so write it like this and make sure you put an array at the end and make sure this is in parentheses right And then let's go ahead and assign that so following props like that and there we go you can see how immediately this error from my side of following has gone away so if yours hasn't confirm that you have the exact same type here and in your follow service make sure you include following true like this. Now go back inside of here and let's extract the data.
And since we marked this as used client it means that we now have access to whether the sidebar is collapsed or not. So let's go ahead and do useSidebar which you can import from store, useSidebar I'm just going to separate the imports Let's get entire state and return it and let's extract collapsed like that and first thing I want to do is if we have no data so if data length is zero right so we can do that quite easily by using this falsy method we're just going to return null so no point in showing anything if we are not following any users otherwise let's go ahead and let's create a div here and dynamically render the label. So if we are not collapsed in that case let's go ahead and render a div here with a class name of PL6 and margin bottom of 4 and inside a paragraph which just says following and now I'm gonna give this paragraph a class name of TextSmall and TextMutedForeground like that so make sure you follow at least one user and I think that already you should be seeing this following tab right here. If you click Unfollow, this should now disappear.
There we go. You can see how it disappears because we do that Revalidate Path, right? Inside of our actions here, you can see that we do Revalidate Path, both on Follow and Unfollow, meaning that all of our server components which in our case is a sidebar gets refetched and thus it has the newest information and it changes according to this if clause right here data.length so when you're not following anyone you should just have the recommended but when you click on follow it should appear for now just a label following because we have enough data to display that so we skip this return null and instead we show this But of course when we are collapsed we cannot see that. So we can only see that when we are expanded, right? And now let's go ahead and render our users and we can do that quite easily because we have the user item component already from the recommended part of our code.
So let's write a class name for this unordered list with space y2 and px of 2 and inside let's do data.map and let's get the individual follow model and then inside let's render the user item from .slash user item so make sure you import user item we already have that right here because we already used it inside of our recommended here so go back inside of the following where we just imported the user item and in here let's go ahead and pass all the necessary props so that's going to be a key which is follow.following so that's the actual user and then we can get the id of the user let's pass in the username which is follow.following.username. Let's pass in the image URL, which is follow.following.imageurl. And let's also pass isLive, which for now we are manually going to change from true or false. So let's put true for now and let's see how this looks like. And there we go you can see how now because I'm following this user I have it in my following tab and when I unfollow this user it's going to disappear from this tab right here and when I follow them back they will immediately appear here.
Perfect! So what I'm gonna do now is I'm gonna remove this is live prop from here because later we're gonna control it with another model which we don't have just yet. So one more thing that I want to add here is the following skeleton. So let's go ahead and do export const following skeleton. And let's return an unordered list.
Let's give it a class name of Px2, padding top 2, button large, padding top is 0 and we're gonna do a mock array. So we're gonna pretend like we are loading 3 users and let's map over them, skipping the first one and going directly to the index. And inside, write down the user item skeleton which you can import from the equally named component user item which we already did here. And all we have to do is pass in the key which is I. Like this.
Great, so make sure that you have the following skeleton. And now what I want to do is I want to add this following skeleton to our sidebar skeleton. So go into the sidebar, find the index. And here we already do the recommended skeleton. So first thing I want to do is I actually want to show the followed users before I show the recommended users.
So let's switch the position of this too. So this is inside of the main sidebar function. Let's move the following to be above recommended. I think that's just better practice. And then let's add the following skeleton above the recommended skeleton.
Great, so this is gonna add that following for our loading functions. I'm not sure if you can see that for a split second now we have the following skeleton. But we also have to add it to one more place if you remember and that is the wrapper because in here we also have a little skeleton for server-side rendering and that hydration issue that we had so just above recommended skeleton add the following skeleton as well so our skeletons now match. So make sure you have this three. So this is the wrapper component inside of our sidebar folder.
Like that. And now everything should be completely fine. So when we are loading here, there we go. You can see we have twice the amount of users that we had before because we are also loading the followed ones and you can see that as well in the mobile mode and we seem to not be having any hydration errors here exactly what we want. And now what I want to do is that when I follow a user I want to remove them from the recommended list the same way we are doing right now with the followed list when we unfollow someone.
So in order to do that we have to revisit our recommended service. So go inside of the lib, recommended service right here. And now we have to modify it only for this clause where we have the actual, where we have the user ID, meaning that the user is logged in. So we have to create two queries. So right now we have a query which says do not recommend yourself meaning do not recommend the currently logged in user but we have to add another one and we can do that by using the end query and that is an array like this and then you have to open an object so go ahead and copy this not and put it inside of this first object like that great so now I will actually do it like this and indent this, there we go And then you can join as many of these queries as you want.
So open another object and then write another not and then write followed by some, open an object again, follower ID, not to never be user ID, meaning that we are not gonna recommend the user if they are following that user, right? So make sure you modified your where query to this. So we added an end property, we opened an array, we opened an object and copied that old not query, then we opened another query here and we specified that we also don't want to be following that user. And now you should only have the following. So expand to your desktop mode and it should only say following.
But if you unfollow the user, it should remove the following and instead it should say recommended. Exactly as we want and if you log out completely, it should still work but both of them should only be in the recommended. When we are logged out we are never gonna have any followed users. Great! So you just wrapped up the follow service and now we're gonna go ahead and we're gonna create the equivalent actions for blocking a user.