Compare commits

...

3 Commits

Author SHA1 Message Date
koreacomp5
98e2f5608d Merge branch 'mainwork' into subwork 2025-11-02 04:59:56 +09:00
koreacomp5
d54ad82095 Merge branch 'subwork' into mainwork 2025-11-02 04:59:21 +09:00
koreacomp5
9c28d50890 main 2025-11-02 04:59:09 +09:00
3 changed files with 26 additions and 16 deletions

View File

@@ -369,6 +369,19 @@ async function seedPartnerShops() {
}); });
} }
async function seedBanners() {
// 기존 배너 정리 후 5개만 채움
await prisma.banner.deleteMany({});
const items = Array.from({ length: 5 }).map((_, i) => ({
title: `메인 배너 ${i + 1}`,
imageUrl: "/sample.jpg",
linkUrl: "/",
sortOrder: i + 1,
active: true,
}));
await prisma.banner.createMany({ data: items });
}
async function main() { async function main() {
await upsertRoles(); await upsertRoles();
const admin = await upsertAdmin(); const admin = await upsertAdmin();
@@ -379,6 +392,7 @@ async function main() {
const boards = await upsertBoards(admin, categoryMap); const boards = await upsertBoards(admin, categoryMap);
await createPostsForAllBoards(boards, 100, admin); await createPostsForAllBoards(boards, 100, admin);
await seedPartnerShops(); await seedPartnerShops();
await seedBanners();
await seedPolicies(); await seedPolicies();

View File

@@ -10,7 +10,6 @@ export default async function BoardDetail({ params, searchParams }: { params: an
const sp = searchParams?.then ? await searchParams : searchParams; const sp = searchParams?.then ? await searchParams : searchParams;
const idOrSlug = p.id as string; const idOrSlug = p.id as string;
const sort = (sp?.sort as "recent" | "popular" | undefined) ?? "recent"; const sort = (sp?.sort as "recent" | "popular" | undefined) ?? "recent";
const period = (sp?.period as string | undefined) ?? "monthly";
// 보드 slug 조회 (새 글 페이지 프리셋 전달) // 보드 slug 조회 (새 글 페이지 프리셋 전달)
const h = await headers(); const h = await headers();
const host = h.get("host") ?? "localhost:3000"; const host = h.get("host") ?? "localhost:3000";
@@ -32,10 +31,13 @@ export default async function BoardDetail({ params, searchParams }: { params: an
let rankingItems: { userId: string; nickname: string; points: number }[] = []; let rankingItems: { userId: string; nickname: string; points: number }[] = [];
if (isSpecialRanking) { if (isSpecialRanking) {
const rankingUrl = new URL(`/api/ranking?period=${encodeURIComponent(period)}`, base).toString(); const topUsers = await prisma.user.findMany({
const rankingRes = await fetch(rankingUrl, { cache: "no-store" }); select: { userId: true, nickname: true, points: true },
const rankingData = await rankingRes.json().catch(() => ({ items: [] })); where: { status: "active" },
rankingItems = rankingData?.items ?? []; orderBy: { points: "desc" },
take: 100,
});
rankingItems = topUsers.map((u) => ({ userId: u.userId, nickname: u.nickname, points: u.points }));
} }
return ( return (
<div className="space-y-6"> <div className="space-y-6">
@@ -49,18 +51,12 @@ export default async function BoardDetail({ params, searchParams }: { params: an
{/* 검색/필터 툴바 + 리스트 */} {/* 검색/필터 툴바 + 리스트 */}
<section> <section>
<BoardToolbar boardId={board?.slug} /> {!isSpecialRanking && <BoardToolbar boardId={board?.slug} />}
<div className="p-0"> <div className="p-0">
{isSpecialRanking ? ( {isSpecialRanking ? (
<div className="rounded-xl border border-neutral-200 overflow-hidden"> <div className="rounded-xl border border-neutral-200 overflow-hidden">
<div className="px-4 py-3 border-b border-neutral-200 flex items-center justify-between bg-[#f6f4f4]"> <div className="px-4 py-3 border-b border-neutral-200 flex items-center justify-between bg-[#f6f4f4]">
<h2 className="text-sm text-neutral-700"> ({period})</h2> <h2 className="text-sm text-neutral-700"> </h2>
<div className="text-xs text-neutral-500 flex gap-2">
<a href={`?period=daily`} className={`px-2 py-0.5 rounded ${period === "daily" ? "bg-neutral-900 text-white" : "bg-white border border-neutral-300"}`}></a>
<a href={`?period=weekly`} className={`px-2 py-0.5 rounded ${period === "weekly" ? "bg-neutral-900 text-white" : "bg-white border border-neutral-300"}`}></a>
<a href={`?period=monthly`} className={`px-2 py-0.5 rounded ${period === "monthly" ? "bg-neutral-900 text-white" : "bg-white border border-neutral-300"}`}></a>
<a href={`?period=all`} className={`px-2 py-0.5 rounded ${period === "all" ? "bg-neutral-900 text-white" : "bg-white border border-neutral-300"}`}></a>
</div>
</div> </div>
<ol className="divide-y divide-neutral-200"> <ol className="divide-y divide-neutral-200">
{rankingItems.map((i, idx) => ( {rankingItems.map((i, idx) => (

View File

@@ -132,7 +132,7 @@ export function HeroBanner({ subItems, activeSubId }: { subItems?: SubItem[]; ac
{/* Pagination - Figma 스타일: 활성은 주황 바, 비활성은 회색 점 (배너 위에 오버랩) */} {/* Pagination - Figma 스타일: 활성은 주황 바, 비활성은 회색 점 (배너 위에 오버랩) */}
{numSlides > 1 && ( {numSlides > 1 && (
<div className="pointer-events-auto absolute bottom-3 left-1/2 -translate-x-1/2 z-10 flex items-center gap-[6px]"> <div className="pointer-events-auto absolute bottom-3 left-1/2 -translate-x-1/2 z-10 flex items-center gap-[10px]">
{banners.map((_, i) => ( {banners.map((_, i) => (
<button <button
key={i} key={i}
@@ -141,8 +141,8 @@ export function HeroBanner({ subItems, activeSubId }: { subItems?: SubItem[]; ac
onClick={() => goTo(i)} onClick={() => goTo(i)}
className={ className={
activeIndex === i activeIndex === i
? "h-[4px] w-[18px] rounded-full bg-[#F94B37]" ? "h-[6px] w-[24px] rounded-full bg-[#F94B37]"
: "h-[6px] w-[6px] rounded-full bg-[rgba(255,255,255,0.6)] hover:bg-white" : "h-[10px] w-[10px] rounded-full bg-[rgba(255,255,255,0.7)] hover:bg-white"
} }
/> />
))} ))}