"use client"; import React, { useEffect, useMemo, useState } from "react"; import { useRouter } from "next/navigation"; type ApiCategory = { id: string; name: string; slug: string; boards: { id: string; name: string; slug: string; type: string; requiresApproval: boolean }[]; }; type PostItem = { id: string; title: string; createdAt: string; boardId: string; }; interface Props { categoryName?: string; categorySlug?: string; } export default function CategoryBoardBrowser({ categoryName, categorySlug }: Props) { const router = useRouter(); const [categories, setCategories] = useState(null); const [selectedBoardId, setSelectedBoardId] = useState(null); const [posts, setPosts] = useState(null); const [isLoadingPosts, setIsLoadingPosts] = useState(false); useEffect(() => { let isMounted = true; (async () => { const res = await fetch("/api/categories", { cache: "no-store" }); const data = await res.json(); if (!isMounted) return; setCategories(data.categories ?? []); })(); return () => { isMounted = false; }; }, []); const selectedCategory = useMemo(() => { if (!categories) return null; // 우선순위: 전달받은 카테고리명 -> 전달받은 슬러그 -> 기본(암실소문/main) const byName = categoryName ? categories.find((c) => c.name === categoryName) : null; if (byName) return byName; const bySlug = categorySlug ? categories.find((c) => c.slug === categorySlug) : null; if (bySlug) return bySlug; return ( categories.find((c) => c.name === "암실소문") || categories.find((c) => c.slug === "main") || null ); }, [categories, categoryName, categorySlug]); const boardIdToName = useMemo(() => { const map = new Map(); if (selectedCategory) { for (const b of selectedCategory.boards) map.set(b.id, b.name); } return map; }, [selectedCategory]); // 기본 보드 자동 선택: 선택된 카테고리의 첫 번째 보드 useEffect(() => { if (!selectedBoardId && selectedCategory?.boards?.length) { setSelectedBoardId(selectedCategory.boards[0].id); } }, [selectedCategory, selectedBoardId]); useEffect(() => { if (!selectedBoardId) return; let isMounted = true; (async () => { try { setIsLoadingPosts(true); const params = new URLSearchParams({ pageSize: String(10), boardId: selectedBoardId }); const res = await fetch(`/api/posts?${params.toString()}`, { cache: "no-store" }); const data = await res.json(); if (!isMounted) return; setPosts(data.items ?? []); } finally { if (isMounted) setIsLoadingPosts(false); } })(); return () => { isMounted = false; }; }, [selectedBoardId]); return (
{/* 상단: 한 줄(row)로 카테고리 + 화살표 + 보드 pill 버튼들 */}
{selectedCategory?.boards?.map((b) => ( ))}
{/* 2행: 게시글 리스트 */}
{!selectedBoardId && (
보드를 선택해 주세요.
)} {selectedBoardId && isLoadingPosts && (
불러오는 중…
)} {selectedBoardId && !isLoadingPosts && posts && posts.length === 0 && (
게시글이 없습니다.
)}
{posts?.map((p) => { const boardName = boardIdToName.get(p.boardId) ?? ""; const dateStr = new Date(p.createdAt).toLocaleDateString(); const imgSrc = `https://picsum.photos/seed/${p.id}/200/140`; return (
썸네일
{boardName}
{p.title}
{dateStr}
); })}
); }