7.2 목록 페이징/정렬/검색(제목/태그/작성자/기간) o
This commit is contained in:
@@ -38,6 +38,10 @@ const listQuerySchema = z.object({
|
||||
boardId: z.string().optional(),
|
||||
q: z.string().optional(),
|
||||
sort: z.enum(["recent", "popular"]).default("recent").optional(),
|
||||
tag: z.string().optional(), // Tag.slug
|
||||
author: z.string().optional(), // User.nickname contains
|
||||
start: z.coerce.date().optional(), // createdAt >= start
|
||||
end: z.coerce.date().optional(), // createdAt <= end
|
||||
});
|
||||
|
||||
export async function GET(req: Request) {
|
||||
@@ -46,7 +50,7 @@ export async function GET(req: Request) {
|
||||
if (!parsed.success) {
|
||||
return NextResponse.json({ error: parsed.error.flatten() }, { status: 400 });
|
||||
}
|
||||
const { page, pageSize, boardId, q, sort = "recent" } = parsed.data;
|
||||
const { page, pageSize, boardId, q, sort = "recent", tag, author, start, end } = parsed.data;
|
||||
const where = {
|
||||
NOT: { status: "deleted" as const },
|
||||
...(boardId ? { boardId } : {}),
|
||||
@@ -58,6 +62,24 @@ export async function GET(req: Request) {
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
...(tag
|
||||
? {
|
||||
postTags: { some: { tag: { slug: tag } } },
|
||||
}
|
||||
: {}),
|
||||
...(author
|
||||
? {
|
||||
author: { nickname: { contains: author } },
|
||||
}
|
||||
: {}),
|
||||
...(start || end
|
||||
? {
|
||||
createdAt: {
|
||||
...(start ? { gte: start } : {}),
|
||||
...(end ? { lte: end } : {}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
} as const;
|
||||
|
||||
const [total, items] = await Promise.all([
|
||||
|
||||
@@ -20,7 +20,7 @@ type Resp = {
|
||||
|
||||
const fetcher = (url: string) => fetch(url).then((r) => r.json());
|
||||
|
||||
export function PostList({ boardId, sort = "recent", q }: { boardId?: string; sort?: "recent" | "popular"; q?: string }) {
|
||||
export function PostList({ boardId, sort = "recent", q, tag, author, start, end }: { boardId?: string; sort?: "recent" | "popular"; q?: string; tag?: string; author?: string; start?: string; end?: string }) {
|
||||
const pageSize = 10;
|
||||
const getKey = (index: number, prev: Resp | null) => {
|
||||
if (prev && prev.items.length === 0) return null;
|
||||
@@ -28,6 +28,10 @@ export function PostList({ boardId, sort = "recent", q }: { boardId?: string; so
|
||||
const sp = new URLSearchParams({ page: String(page), pageSize: String(pageSize), sort });
|
||||
if (boardId) sp.set("boardId", boardId);
|
||||
if (q) sp.set("q", q);
|
||||
if (tag) sp.set("tag", tag);
|
||||
if (author) sp.set("author", author);
|
||||
if (start) sp.set("start", start);
|
||||
if (end) sp.set("end", end);
|
||||
return `/api/posts?${sp.toString()}`;
|
||||
};
|
||||
const { data, size, setSize, isLoading } = useSWRInfinite<Resp>(getKey, fetcher);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { PostList } from "@/app/components/PostList";
|
||||
|
||||
export default function SearchPage({ searchParams }: { searchParams?: { q?: string; sort?: "recent" | "popular" } }) {
|
||||
export default function SearchPage({ searchParams }: { searchParams?: { q?: string; sort?: "recent" | "popular"; tag?: string; author?: string; start?: string; end?: string } }) {
|
||||
const q = searchParams?.q ?? "";
|
||||
const sort = searchParams?.sort ?? "recent";
|
||||
const { tag = "", author = "", start = "", end = "" } = searchParams ?? {};
|
||||
return (
|
||||
<div>
|
||||
<h2 style={{ marginBottom: 12 }}>검색: {q || "전체"}</h2>
|
||||
<PostList q={q} sort={sort} />
|
||||
<h2 style={{ marginBottom: 12 }}>검색: {q || tag || author || (start && end ? `${start}~${end}` : "전체")}</h2>
|
||||
<PostList q={q} sort={sort} tag={tag} author={author} start={start} end={end} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
[게시판/컨텐츠]
|
||||
7.1 게시글 CRUD API 및 페이지 연동 o
|
||||
7.2 목록 페이징/정렬/검색(제목/태그/작성자/기간)
|
||||
7.2 목록 페이징/정렬/검색(제목/태그/작성자/기간) o
|
||||
7.3 태그/카테고리 모델 및 UI
|
||||
7.4 첨부 업로드 및 본문 삽입
|
||||
7.5 추천/신고, 조회수 카운트
|
||||
|
||||
Reference in New Issue
Block a user