From 65ecff6147a7e13d0d1ac0804a2c32bcbf6a8e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20Akg=C3=BCl?= <s86116@bht-berlin.de> Date: Wed, 5 Jul 2023 16:11:46 +0200 Subject: [PATCH] profile page remake 1 --- .../(user)/[userid]/(profile)/media/page.tsx | 7 + .../[userid]/(profile)/with_replies/page.tsx | 7 + app/api/followers/route.ts | 82 ----------- app/api/users/[id]/route.ts | 102 ++++++++++++++ app/api/users/favgameslist/route.ts | 6 +- app/api/users/follow/route.ts | 129 ++++++++++++++++++ app/api/users/route.ts | 44 ++++++ components/following-button.tsx | 8 +- prisma/schema.prisma | 16 +-- 9 files changed, 298 insertions(+), 103 deletions(-) create mode 100644 app/(content)/(user)/[userid]/(profile)/media/page.tsx create mode 100644 app/(content)/(user)/[userid]/(profile)/with_replies/page.tsx delete mode 100644 app/api/followers/route.ts create mode 100644 app/api/users/[id]/route.ts create mode 100644 app/api/users/follow/route.ts create mode 100644 app/api/users/route.ts diff --git a/app/(content)/(user)/[userid]/(profile)/media/page.tsx b/app/(content)/(user)/[userid]/(profile)/media/page.tsx new file mode 100644 index 0000000..0d06dc6 --- /dev/null +++ b/app/(content)/(user)/[userid]/(profile)/media/page.tsx @@ -0,0 +1,7 @@ +export default async function Media() { + return ( + <div> + <h1>Media Page WIP</h1> + </div> + ) +} \ No newline at end of file diff --git a/app/(content)/(user)/[userid]/(profile)/with_replies/page.tsx b/app/(content)/(user)/[userid]/(profile)/with_replies/page.tsx new file mode 100644 index 0000000..83676c5 --- /dev/null +++ b/app/(content)/(user)/[userid]/(profile)/with_replies/page.tsx @@ -0,0 +1,7 @@ +export default async function WithReplies() { + return ( + <div> + <h1>WithReplies Page WIP</h1> + </div> + ) +} \ No newline at end of file diff --git a/app/api/followers/route.ts b/app/api/followers/route.ts deleted file mode 100644 index cc32720..0000000 --- a/app/api/followers/route.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { db } from "@/lib/db" -import { getCurrentUser } from "@/lib/session" -import { revalidatePath } from "next/cache" -import { NextRequest, NextResponse } from "next/server" - -export async function GET(req: NextRequest) { - const sessionUser = await getCurrentUser() - - if (!sessionUser) { - return NextResponse.json({ status: 401, message: 'Unauthorized' }) - } - let follows = undefined - - try { - follows = await db.follows.findMany({ - where: { - followerId: sessionUser.id - } - }) - } catch (error) { - console.log("error", error) - } - - return NextResponse.json({ status: 200, message: "fetched follows", follows }) -} - -export async function PUT(req: NextRequest) { - const sessionUser = await getCurrentUser() - - const data = await req.json() - - if (!sessionUser) { - return NextResponse.json({ status: 401, message: 'Unauthorized' }) - } - - try { - const dbUser = await db.user.findFirst({ - where: { - id: sessionUser.id - } - }) - - const follow = await db.follows.findFirst({ - where: { - followerId: sessionUser.id, - followingId: data.followingId - } - }) - console.log("follow", follow) - - if (follow) { - // User is already following, so unfollow - console.log("delete follow") - const delfollow = await db.follows.delete({ - where: { - followerId_followingId: { - followerId: sessionUser.id, - followingId: data.followingId - } - - } - }) - console.log("del follow:", delfollow) - } else { - // User is not following, so follow - console.log("create follow") - await db.follows.create({ - data: { - followerId: sessionUser.id, - followingId: data.followingId - }, - }) - - } - } catch (error) { - console.log("err", error) - } - const path = req.nextUrl.searchParams.get('path') || '/' - revalidatePath(path) - - return NextResponse.json({ status: 200, message: 'Follow handled' }) -} \ No newline at end of file diff --git a/app/api/users/[id]/route.ts b/app/api/users/[id]/route.ts new file mode 100644 index 0000000..c0bb2b0 --- /dev/null +++ b/app/api/users/[id]/route.ts @@ -0,0 +1,102 @@ +import { db } from "@/lib/db" +import { NextResponse } from "next/server" +import { z } from "zod" + +export async function GET(request: Request, context: { params: { id: string } }) { + const { id } = context.params + + const idSchema = z.string().cuid() + const zod = idSchema.safeParse(id) + + if (!zod.success) { + return NextResponse.json(zod.error, { status: 400 }) + } + + try { + const user = await db.user.findUnique({ + where: { + id, + }, + + select: { + id: true, + name: true, + username: true, + email: true, + image: true, + banner: true, + + createdAt: true, + bio: true, + location: true, + followers: true, + following: true, + + _count: { + select: { + followers: true, + following: true, + }, + }, + }, + }) + + return NextResponse.json(user, { status: 200 }) + } catch (error: any) { + return NextResponse.json(error.message, { status: 500 }) + } +} + +export async function PUT(request: Request) { + const { + userId, + name, + bio, + location, + banner, + image, + } = await request.json() + + const userSchema = z + .object({ + userId: z.string().cuid(), + name: z.string().min(1).max(50), + bio: z.string().max(160), + location: z.string().max(30), + banner: z.string(), + image: z.string(), + }) + .strict() + + const zod = userSchema.safeParse({ + userId, + name, + bio, + location, + banner, + image, + }) + + if (!zod.success) { + return NextResponse.json(zod.error, { status: 400 }) + } + + try { + const user = await db.user.update({ + where: { + id: userId, + }, + data: { + name, + bio, + location, + banner, + image, + }, + }) + + return NextResponse.json(user, { status: 200 }) + } catch (error: any) { + return NextResponse.json(error.message, { status: 500 }) + } +} \ No newline at end of file diff --git a/app/api/users/favgameslist/route.ts b/app/api/users/favgameslist/route.ts index 7b06bea..967f901 100644 --- a/app/api/users/favgameslist/route.ts +++ b/app/api/users/favgameslist/route.ts @@ -4,13 +4,13 @@ import { revalidatePath } from "next/cache" import { NextRequest, NextResponse } from "next/server" export async function PUT(req: NextRequest) { - const user = await getCurrentUser() + const session = await getCurrentUser() - if (!user) { + if (!session) { return NextResponse.json({ status: 401, message: 'Unauthorized' }) } - const userId = user.id + const userId = session.id const data = await req.json() data.gameId = parseInt(data.gameId) diff --git a/app/api/users/follow/route.ts b/app/api/users/follow/route.ts new file mode 100644 index 0000000..3c6dc93 --- /dev/null +++ b/app/api/users/follow/route.ts @@ -0,0 +1,129 @@ +import { db } from "@/lib/db" +import { getCurrentUser } from "@/lib/session" +import { NextResponse } from "next/server" +import { z } from "zod" + +// get following or followers information +export async function GET(request: Request) { + const { searchParams } = new URL(request.url) + const userId = searchParams.get("userId") || undefined + const type = searchParams.get("type") || undefined + + const userIdSchema = z.string().cuid().optional() + const zod = userIdSchema.safeParse(userId) + + if (!zod.success) { + return NextResponse.json(zod.error, { status: 400 }) + } + + try { + if (type === "followers") { + const followers = await db.user + .findUnique({ + where: { + id: userId, + }, + }) + .followers() + return NextResponse.json(followers, { status: 200 }) + } else if (type === "following") { + const following = await db.user + .findUnique({ + where: { + id: userId, + }, + }) + .following() + + return NextResponse.json(following, { status: 200 }) + } + } catch (error: any) { + return NextResponse.json(error.message, { status: 500 }) + } +} + +// follow a user +export async function PUT(request: Request) { + const session = await getCurrentUser() + const { userId } = await request.json() + + const followerIdSchema = z + .object({ + userId: z.string().cuid(), + }) + .strict() + + const zod = followerIdSchema.safeParse({ userId }) + + if (!zod.success) { + return NextResponse.json(zod.error, { status: 400 }) + } + + try { + await db.user.update({ + where: { + id: userId, + }, + + data: { + followers: { + connect: { + id: session?.id, + }, + }, + }, + }) + + return NextResponse.json( + { + message: "followed", + }, { status: 200 } + ) + } catch (error: any) { + return NextResponse.json(error.message, { status: 500 }) + } +} + +// unfollow a user +export async function DELETE(request: Request) { + const session = await getCurrentUser() + const { searchParams } = new URL(request.url) + + const userId = searchParams.get("userId") || undefined + + const followerIdSchema = z + .object({ + userId: z.string().cuid(), + }) + .strict() + + const zod = followerIdSchema.safeParse({ userId }) + + if (!zod.success) { + return NextResponse.json(zod.error, { status: 400 }) + } + + try { + await db.user.update({ + where: { + id: userId, + }, + + data: { + followers: { + disconnect: { + id: session?.id, + }, + }, + }, + }) + + return NextResponse.json( + { + message: "unfollowed", + }, { status: 200 }, + ) + } catch (error: any) { + return NextResponse.json(error.message, { status: 500 }) + } +} \ No newline at end of file diff --git a/app/api/users/route.ts b/app/api/users/route.ts new file mode 100644 index 0000000..e0611fd --- /dev/null +++ b/app/api/users/route.ts @@ -0,0 +1,44 @@ +import { db } from "@/lib/db" +import { NextResponse } from "next/server" +import { z } from "zod" + +// get all other users +export async function GET(request: Request) { + const { searchParams } = new URL(request.url) + const id = searchParams.get("id") || undefined + const idSchema = z.string().cuid().optional() + + const zod = idSchema.safeParse(id) + + if (!zod.success) { + return NextResponse.json(zod.error, { status: 400 }) + } + + try { + const users = await db.user.findMany({ + where: { + NOT: { + id, + }, + }, + + orderBy: { + createdAt: "desc", + }, + + select: { + id: true, + name: true, + username: true, + email: true, + image: true, + following: true, + followers: true, + }, + }) + + return NextResponse.json(users, { status: 200 }) + } catch (error: any) { + return NextResponse.json(error.message, { status: 500 }) + } +} \ No newline at end of file diff --git a/components/following-button.tsx b/components/following-button.tsx index b5eb3f4..4634282 100644 --- a/components/following-button.tsx +++ b/components/following-button.tsx @@ -1,6 +1,6 @@ "use client" -import { Follows, Prisma } from '@prisma/client' +import { Prisma } from '@prisma/client' import { useSession } from 'next-auth/react' import { usePathname } from "next/navigation" import { useEffect, useState } from 'react' @@ -31,12 +31,12 @@ export default function FollowButton({ user, followingId }: { user: UserWithFoll async function fetchFollows() { try { - const response = await fetch('/api/followers') + const response = await fetch('/api/users/follow') const data = await response.json() setFollows(data.follows) setIsFollowing(false) - data.follows?.forEach((f: Follows) => { + data.follows?.forEach((f: any) => { if (f.followerId == user.id && f.followingId == followingId) { setIsFollowing(true) @@ -56,7 +56,7 @@ export default function FollowButton({ user, followingId }: { user: UserWithFoll async function handleFollow(e: any) { e.preventDefault() - const response = await fetch('/api/followers', { + const response = await fetch('/api/users/follow', { method: 'PUT', body: JSON.stringify({ user, followingId }) }) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9deaae8..d6b3ef1 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -81,24 +81,12 @@ model User { regweets Regweet[] likes Like[] - following Follows[] @relation("following") - followers Follows[] @relation("follower") + following User[] @relation("followers") + followers User[] @relation("followers") @@map("users") } -model Follows { - followerId String - followingId String - createdAt DateTime @default(now()) @map("created_at") - - follower User @relation("following", fields: [followerId], references: [id]) - following User @relation("follower", fields: [followingId], references: [id]) - - @@id([followerId, followingId]) - @@map("follows") -} - model Gweet { id String @id @default(cuid()) authorId String @map("user_id") -- GitLab