import { HeroBanner } from "@/app/components/HeroBanner"; import Link from "next/link"; import HorizontalCardScroller from "@/app/components/HorizontalCardScroller"; import { PostList } from "@/app/components/PostList"; import ProfileLabelIcon from "@/app/svgs/profilelableicon"; import SearchIcon from "@/app/svgs/SearchIcon"; import prisma from "@/lib/prisma"; export default async function Home({ searchParams }: { searchParams: Promise<{ sort?: "recent" | "popular" } | undefined> }) { const sp = await searchParams; const sort = sp?.sort ?? "recent"; // 메인페이지 설정 불러오기 const SETTINGS_KEY = "mainpage_settings" as const; const settingRow = await prisma.setting.findUnique({ where: { key: SETTINGS_KEY } }); const parsed = settingRow ? JSON.parse(settingRow.value as string) : {}; const showBanner: boolean = parsed.showBanner ?? true; const showPartnerShops: boolean = parsed.showPartnerShops ?? true; const visibleBoardIds: string[] = Array.isArray(parsed.visibleBoardIds) ? parsed.visibleBoardIds : []; // 보드 메타데이터 (메인뷰 타입 포함) const boardsMeta = visibleBoardIds.length ? await prisma.board.findMany({ where: { id: { in: visibleBoardIds } }, select: { id: true, name: true, slug: true, category: { select: { id: true, name: true } }, mainPageViewType: { select: { key: true } }, }, }) : []; const idToMeta = new Map( boardsMeta.map((b) => [ b.id, { id: b.id, name: b.name, slug: b.slug, categoryId: b.category?.id ?? null, categoryName: b.category?.name ?? "", mainTypeKey: b.mainPageViewType?.key, }, ] as const) ); const orderedBoards = visibleBoardIds .map((id) => idToMeta.get(id)) .filter((v): v is any => Boolean(v)); const firstTwo = orderedBoards.slice(0, 2); const restBoards = orderedBoards.slice(2); function formatDateYmd(d: Date) { const yyyy = d.getFullYear(); const mm = String(d.getMonth() + 1).padStart(2, "0"); const dd = String(d.getDate()).padStart(2, "0"); return `${yyyy}.${mm}.${dd}`; } const renderBoardPanel = async (board: { id: string; name: string; slug: string; categoryId: string | null; categoryName: string; mainTypeKey?: string }) => { // 같은 카테고리의 소분류(게시판) 탭 목록 const siblingBoards = board.categoryId ? await prisma.board.findMany({ where: { categoryId: board.categoryId }, select: { id: true, name: true, slug: true }, orderBy: [{ sortOrder: "asc" }, { name: "asc" }], }) : []; const isTextMain = board.mainTypeKey === "main_text"; if (!isTextMain) { return (
{board.categoryName || board.name}
{siblingBoards.map((sb) => ( {sb.name} ))}
{board.name} 더보기
); } const posts = await prisma.post.findMany({ where: { boardId: board.id, status: "published" }, select: { id: true, title: true, createdAt: true, stat: { select: { recommendCount: true } } }, orderBy: { createdAt: "desc" }, take: 8, }); return (
{board.categoryName || board.name}
{siblingBoards.map((sb) => ( {sb.name} ))}
{board.name} 더보기
    {posts.map((p) => (
  • n
    {p.title} +{p.stat?.recommendCount ?? 0}
    {formatDateYmd(new Date(p.createdAt))}
  • ))}
); }; return (
{/* 히어로 섹션: 상단 대형 비주얼 영역 (설정 온오프) */} {showBanner && (
)} {/* 제휴 샾 가로 스크롤 (설정 온오프, DB에서 불러오기) - 우선 partners 테이블(관리자 페이지 관리 대상) 사용 - 없으면 partner_shops로 대체 */} {showPartnerShops && (async () => { // 우선순위: partners(관리자 관리) → partner_shops(폴백) let partners: any[] = []; try { partners = await (prisma as any).partner.findMany({ orderBy: [{ sortOrder: "asc" }, { createdAt: "desc" }], take: 10 }); } catch (_) { partners = await prisma.partner.findMany({ orderBy: { createdAt: "desc" }, take: 10 }); } const items = partners.map((p: any) => ({ id: p.id, region: p.address ? String(p.address).split(" ")[0] : p.category, name: p.name, address: p.address || "", image: p.imageUrl || "/sample.jpg", })); if (items.length > 0) return ; const shops = await (prisma as any).partnerShop.findMany({ where: { active: true }, orderBy: [{ sortOrder: "asc" }, { createdAt: "desc" }] }); const shopItems = shops.map((s: any) => ({ id: s.id, region: s.region, name: s.name, address: s.address, image: s.imageUrl })); return ; })()} {/* 1행: 프로필 + 선택된 보드 2개 (최대 2개) */} {(firstTwo.length > 0) && (
프로필
Lv
홍길동
레벨
Lv. 79
등급
Iron
포인트
1,600,000
{(await Promise.all(firstTwo.map((b) => renderBoardPanel(b)))).map((panel, idx) => (
{panel}
))}
)} {/* 나머지 보드: 2개씩 다음 열로 렌더링 */} {restBoards.length > 0 && ( <> {Array.from({ length: Math.ceil(restBoards.length / 2) }).map(async (_, i) => { const pair = restBoards.slice(i * 2, i * 2 + 2); return (
{(await Promise.all(pair.map((b) => renderBoardPanel(b)))).map((panel, idx) => (
{panel}
))}
); })} )}
); }