import { headers } from "next/headers"; import { redirect } from "next/navigation"; import prisma from "@/lib/prisma"; import Link from "next/link"; import { UserAvatar } from "@/app/components/UserAvatar"; import { GradeIcon, getGradeName } from "@/app/components/GradeIcon"; import { HeroBanner } from "@/app/components/HeroBanner"; import { PostList } from "@/app/components/PostList"; import ProfileLabelIcon from "@/app/svgs/profilelableicon"; import { ProfileEditTrigger } from "@/app/components/ProfileEditTrigger"; import { SendMessageForm } from "@/app/components/SendMessageForm"; export default async function MyPage({ searchParams }: { searchParams: Promise<{ tab?: string; page?: string; sort?: string; q?: string; to?: string }> }) { const sp = await searchParams; const activeTab = sp?.tab || "posts"; const page = parseInt(sp?.page || "1", 10); const sort = sp?.sort || "recent"; const q = sp?.q || ""; const toUserId = sp?.to || ""; // 현재 로그인한 사용자 정보 가져오기 let currentUser: { userId: string; nickname: string; profileImage: string | null; points: number; level: number; grade: number; } | null = null; try { const h = await headers(); const cookieHeader = h.get("cookie") || ""; let isAdmin = false; const uid = cookieHeader .split(";") .map((s) => s.trim()) .find((pair) => pair.startsWith("uid=")) ?.split("=")[1]; const isAdminVal = cookieHeader .split(";") .map((s) => s.trim()) .find((pair) => pair.startsWith("isAdmin=")) ?.split("=")[1]; isAdmin = isAdminVal === "1"; if (!uid) { redirect(`/login?next=/my-page`); } if (uid) { const user = await prisma.user.findUnique({ where: { userId: decodeURIComponent(uid) }, select: { userId: true, nickname: true, profileImage: true, points: true, level: true, grade: true }, }); if (user) { currentUser = { ...user, isAdmin } as any; } else { redirect(`/login?next=/my-page`); } } } catch (e) { // 에러 무시 } if (!currentUser) redirect(`/login?next=/my-page`); // 통계 정보 가져오기 const [postsCount, commentsCount, receivedMessagesCount, sentMessagesCount] = await Promise.all([ prisma.post.count({ where: { authorId: currentUser.userId } }), prisma.comment.count({ where: { authorId: currentUser.userId } }), prisma.message.count({ where: { receiverId: currentUser.userId } }), prisma.message.count({ where: { senderId: currentUser.userId } }), ]); // 등급 업그레이드에 필요한 포인트 계산 (예시: 다음 등급까지) const nextGradePoints = (() => { // 등급별 포인트 기준을 여기에 설정 (임시로 2M) const gradeThresholds = [0, 200000, 400000, 800000, 1600000, 3200000, 6400000, 10000000]; const currentGradeIndex = Math.min(7, Math.max(0, currentUser.grade)); return gradeThresholds[currentGradeIndex + 1] || 2000000; })(); const tabs = [ { key: "posts", label: "내가 쓴 게시글", count: postsCount }, { key: "comments", label: "내가 쓴 댓글", count: commentsCount }, { key: "points", label: "포인트 히스토리", count: await prisma.pointTransaction.count({ where: { userId: currentUser.userId } }) }, { key: "messages-received", label: "받은 쪽지함", count: receivedMessagesCount }, { key: "messages-sent", label: "보낸 쪽지함", count: sentMessagesCount }, ]; return (
{/* 히어로 배너 */}
{/* 프로필 섹션 (모바일 대응) */}
{/* 좌측: 프로필 이미지, 닉네임, 레벨/등급/포인트 */}
{/* 프로필 이미지 */}
{/* 닉네임 */}
{currentUser.nickname || "사용자"}
{/* 관리자 설정 버튼 */} {"isAdmin" in (currentUser as any) && (currentUser as any).isAdmin && (
관리자설정
)}
{/* 프로필 수정은 연필 아이콘(모달)에서 처리 */} {/* 레벨/등급/포인트 정보 - 가로 배치 */}
레벨 Lv.{currentUser.level || 1}
등급 {getGradeName(currentUser.grade)}
포인트 {currentUser.points.toLocaleString()}
{/* 구분선 (모바일 숨김) */}
{/* 우측: 등급 배지 및 포인트 진행 상황 */}
{getGradeName(currentUser.grade)}
{(currentUser.points / 1000000).toFixed(1)}M / {(nextGradePoints / 1000000).toFixed(1)}M
{/* 탭 버튼 (모바일 가로 스크롤) */}
{tabs.map((tab) => ( {tab.label}
{tab.count.toLocaleString()}
))}
{/* 컨텐츠 영역 */}
{activeTab === "posts" && ( )} {activeTab === "comments" && (async () => { const pageSize = 20; const comments = await prisma.comment.findMany({ where: { authorId: currentUser.userId }, orderBy: { createdAt: "desc" }, take: pageSize, skip: (page - 1) * pageSize, select: { id: true, postId: true, content: true, createdAt: true }, }); return (
    {comments.map((c) => (
  • {c.content.slice(0, 80)}{c.content.length > 80 ? "…" : ""} {new Date(c.createdAt).toLocaleString()}
  • ))}
); })()} {activeTab === "points" && (async () => { const pageSize = 20; const txns = await prisma.pointTransaction.findMany({ where: { userId: currentUser.userId }, orderBy: { createdAt: "desc" }, take: pageSize, skip: (page - 1) * pageSize, select: { id: true, amount: true, reason: true, createdAt: true }, }); return (
    {txns.map((t) => (
  • {t.reason}
    = 0 ? 'text-green-600' : 'text-red-600'}`}> {t.amount >= 0 ? `+${t.amount}` : `${t.amount}`}
    {new Date(t.createdAt).toLocaleString()}
  • ))}
); })()} {activeTab === "messages-received" && (async () => { const pageSize = 20; // 받은 쪽지함 진입 시 미읽은 메시지를 읽음 처리 await prisma.message.updateMany({ where: { receiverId: currentUser.userId, readAt: null }, data: { readAt: new Date() }, }); const messages = await prisma.message.findMany({ where: { receiverId: currentUser.userId }, orderBy: { createdAt: "desc" }, take: pageSize, skip: (page - 1) * pageSize, select: { id: true, body: true, createdAt: true, sender: { select: { userId: true, nickname: true } } }, }); return (
    {messages.map((m) => (
  • {m.sender.nickname || "알 수 없음"} {new Date(m.createdAt).toLocaleString()}
    {m.body}
  • ))}
); })()} {activeTab === "messages-sent" && (async () => { const pageSize = 20; const receiver = toUserId ? await prisma.user.findUnique({ where: { userId: toUserId }, select: { userId: true, nickname: true } }) : null; const messages = await prisma.message.findMany({ where: { senderId: currentUser.userId }, orderBy: { createdAt: "desc" }, take: pageSize, skip: (page - 1) * pageSize, select: { id: true, body: true, createdAt: true, receiver: { select: { userId: true, nickname: true } } }, }); return (
{receiver ? (
) : (
닉네임 메뉴에서 ‘쪽지쓰기’를 클릭하면 작성 폼이 나타납니다.
)}

보낸 쪽지

    {messages.map((m) => (
  • {m.receiver.nickname || "알 수 없음"} {new Date(m.createdAt).toLocaleString()}
    {m.body}
  • ))}
); })()}
); }