Skip to content

Commit

Permalink
feat: implement follow and unfollow functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
acatzk committed Feb 6, 2024
1 parent bebe498 commit c23ecef
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 17 deletions.
52 changes: 49 additions & 3 deletions components/suggested-user-item.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,61 @@
import React from 'react'
import Link from 'next/link'
import { toast } from 'sonner'
import Image from 'next/image'

import { trpc } from '~/trpc/client'
import { IUser } from '~/helpers/interfaces'
import { Button } from '~/components/ui/button'

type SuggestedUserItemProps = {
user: IUser
isFollowed: boolean
authorId: number
}

export const SuggestedUserItem = (props: SuggestedUserItemProps): JSX.Element => {
const { username, imageUrl, displayName } = props.user
const { id, username, imageUrl, displayName } = props.user
const { isFollowed, authorId } = props

const utils = trpc.useContext()
const follow = trpc.follow.follow.useMutation()
const unfollow = trpc.follow.unfollow.useMutation()

const handleFollowUnfollow = async (): Promise<void> => {
if (isFollowed) {
await unfollow.mutateAsync(
{
authorId,
targetId: id
},
{
onSuccess: () => {
utils.user.getSuggestedUsers.invalidate()

Check failure on line 33 in components/suggested-user-item.tsx

View workflow job for this annotation

GitHub Actions / Build frontend

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
toast.success(`You unfollow ${displayName}`)
},
onError: () => {
toast.error(`Something went wrong unfollowing ${displayName}`)
}
}
)
} else {
await follow.mutateAsync(
{
authorId,
targetId: id
},
{
onSuccess: () => {
utils.user.getSuggestedUsers.invalidate()

Check failure on line 49 in components/suggested-user-item.tsx

View workflow job for this annotation

GitHub Actions / Build frontend

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
toast.success(`You follow ${displayName}`)
},
onError: () => {
toast.error(`Something went wrong following ${displayName}`)
}
}
)
}
}

return (
<li className="flex items-center justify-between">
Expand All @@ -31,11 +76,12 @@ export const SuggestedUserItem = (props: SuggestedUserItemProps): JSX.Element =>
</Link>
<Button
type="button"
variant="primary-outline"
variant={isFollowed ? 'secondary-outline' : 'primary'}
className="w-20 text-xs font-semibold"
onClick={handleFollowUnfollow}

Check failure on line 81 in components/suggested-user-item.tsx

View workflow job for this annotation

GitHub Actions / Build frontend

Promise-returning function provided to attribute where a void return was expected
size="xs"
>
Follow
{isFollowed ? 'Following' : 'Follow'}
</Button>
</li>
)
Expand Down
20 changes: 19 additions & 1 deletion components/suggested-user-list.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import { FetchNextPageOptions, InfiniteQueryObserverResult } from '@tanstack/react-query'

import { trpc } from '~/trpc/client'
import { IUser } from '~/helpers/interfaces'
import { Spinner } from '~/components/custom-icon/spinner'
import { SuggestedUserItem } from '~/components/suggested-user-item'
Expand Down Expand Up @@ -29,15 +30,32 @@ type SuggestedUserListProps = {
export const SuggestedUserList = (props: SuggestedUserListProps): JSX.Element => {
const { users, fetchNextPage, hasNextPage, isFetchingNextPage } = props

const currentUser = trpc.user.currentUser.useQuery()
const authorId = Number(currentUser?.data?.id)
const followStatuses = trpc.useQueries(
(t) =>
users?.map((user) =>
t.follow.checkUserFollowed({
targetId: user.id
})
) as any
)

return (
<nav className="mt-5">
<ul className="flex flex-col space-y-6">
{users?.map((user, index) => {
const followCheckResult = followStatuses[index]?.data
const isFollowed = followCheckResult?.checkUserFollowed ?? false
console.log(followCheckResult)

Check failure on line 50 in components/suggested-user-list.tsx

View workflow job for this annotation

GitHub Actions / Build frontend

Unexpected console statement

return (
<SuggestedUserItem
key={index}
{...{
user
user,
isFollowed,
authorId
}}
/>
)
Expand Down
4 changes: 2 additions & 2 deletions components/suggestion-rightbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { FileWarningIcon } from 'lucide-react'
import { Remind, UploadOne } from '@icon-park/react'

import { cn } from '~/lib/utils'
import { trpc } from '~/trpc/client'
import { IUser } from '~/helpers/interfaces'
import { useUpload } from '~/hooks/use-upload'
import { Spinner } from '~/components/custom-icon/spinner'

import { trpc } from '~/trpc/client'
import { SearchField } from './search-field'
import { IUser } from '~/helpers/interfaces'
import { SuggestedUserList } from './suggested-user-list'
import { Alert, AlertDescription, AlertTitle } from './ui/alert'

Expand Down
32 changes: 21 additions & 11 deletions server/api/routers/follow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const UserRelation = z.object({
})

export const followRouter = createTRPCRouter({
follow: protectedProcedure.input(UserRelation).query(async ({ ctx, input }) => {
follow: protectedProcedure.input(UserRelation).mutation(async ({ ctx, input }) => {
if (input.authorId === input.targetId) {
throw new TRPCError({
code: 'BAD_REQUEST',
Expand Down Expand Up @@ -48,7 +48,7 @@ export const followRouter = createTRPCRouter({
})
}),

unfollow: protectedProcedure.input(UserRelation).query(async ({ ctx, input }) => {
unfollow: protectedProcedure.input(UserRelation).mutation(async ({ ctx, input }) => {
if (input.authorId === input.targetId) {
throw new TRPCError({
code: 'BAD_REQUEST',
Expand Down Expand Up @@ -81,16 +81,26 @@ export const followRouter = createTRPCRouter({
})
}),

checkUserFollowed: protectedProcedure.input(UserRelation).query(({ ctx, input }) => {
const followRelationship = ctx.db.follow.findUnique({
where: {
followerId_followingId: {
checkUserFollowed: protectedProcedure
.input(UserRelation.pick({ targetId: true }))
.query(({ ctx, input }) => {
// const followRelationship = ctx.db.follow.findUnique({
// where: {
// followerId_followingId: {
// followerId: input.targetId,
// followingId: input.authorId
// }
// }
// })
const followRelationship = ctx.db.follow.findMany({
where: {
followerId: input.targetId,
followingId: input.authorId
following: {
externalId: ctx.auth.userId
}
}
}
})
})

return !!followRelationship
})
return !!followRelationship
})
})

0 comments on commit c23ecef

Please sign in to comment.