76 lines
3.4 KiB
TypeScript
76 lines
3.4 KiB
TypeScript
|
|
"use client";
|
||
|
|
import { useRouter, useSearchParams } from "next/navigation";
|
||
|
|
import React from "react";
|
||
|
|
|
||
|
|
export function BoardToolbar({ boardId }: { boardId: string }) {
|
||
|
|
const router = useRouter();
|
||
|
|
const sp = useSearchParams();
|
||
|
|
const sort = (sp.get("sort") as "recent" | "popular" | null) ?? "recent";
|
||
|
|
const scope = (sp.get("scope") as "q" | "author" | null) ?? "q"; // q: 제목+내용, author: 작성자
|
||
|
|
const defaultText = scope === "author" ? sp.get("author") ?? "" : sp.get("q") ?? "";
|
||
|
|
const period = sp.get("period") ?? "all"; // all | 1d | 1w | 1m
|
||
|
|
|
||
|
|
const onChangeSort = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||
|
|
const next = new URLSearchParams(sp.toString());
|
||
|
|
next.set("sort", e.target.value);
|
||
|
|
router.push(`/boards/${boardId}?${next.toString()}`);
|
||
|
|
};
|
||
|
|
|
||
|
|
const onChangePeriod = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||
|
|
const next = new URLSearchParams(sp.toString());
|
||
|
|
const v = e.target.value;
|
||
|
|
next.set("period", v);
|
||
|
|
// 계산된 start 적용
|
||
|
|
const now = new Date();
|
||
|
|
if (v === "1d") now.setDate(now.getDate() - 1);
|
||
|
|
if (v === "1w") now.setDate(now.getDate() - 7);
|
||
|
|
if (v === "1m") now.setMonth(now.getMonth() - 1);
|
||
|
|
if (v === "all") next.delete("start"); else next.set("start", now.toISOString());
|
||
|
|
router.push(`/boards/${boardId}?${next.toString()}`);
|
||
|
|
};
|
||
|
|
|
||
|
|
const onSubmit = (formData: FormData) => {
|
||
|
|
const next = new URLSearchParams(sp.toString());
|
||
|
|
const scopeSel = String(formData.get("scope") || "q");
|
||
|
|
const text = String(formData.get("text") || "");
|
||
|
|
next.set("scope", scopeSel);
|
||
|
|
if (scopeSel === "author") {
|
||
|
|
next.delete("q");
|
||
|
|
if (text) next.set("author", text); else next.delete("author");
|
||
|
|
} else {
|
||
|
|
next.delete("author");
|
||
|
|
if (text) next.set("q", text); else next.delete("q");
|
||
|
|
}
|
||
|
|
router.push(`/boards/${boardId}?${next.toString()}`);
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="flex items-center justify-between px-0 py-2">
|
||
|
|
<div className="flex items-center gap-2">
|
||
|
|
<select aria-label="정렬" className="h-8 px-2 rounded-md border border-neutral-300 bg-white text-sm" defaultValue={sort} onChange={onChangeSort}>
|
||
|
|
<option value="recent">최신순</option>
|
||
|
|
<option value="popular">인기순</option>
|
||
|
|
</select>
|
||
|
|
<select aria-label="기간" className="h-8 px-2 rounded-md border border-neutral-300 bg-white text-sm" defaultValue={period} onChange={onChangePeriod}>
|
||
|
|
<option value="all">전체기간</option>
|
||
|
|
<option value="1d">24시간</option>
|
||
|
|
<option value="1w">1주일</option>
|
||
|
|
<option value="1m">1개월</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
<form action={onSubmit} className="flex items-center gap-2">
|
||
|
|
<select name="scope" aria-label="검색대상" className="h-8 px-2 rounded-md border border-neutral-300 bg-white text-sm" defaultValue={scope}>
|
||
|
|
<option value="q">제목+내용</option>
|
||
|
|
<option value="author">작성자</option>
|
||
|
|
</select>
|
||
|
|
<input name="text" defaultValue={defaultText} placeholder="검색어를 입력해 주세요." className="h-8 w-56 md:w-72 px-3 rounded-md border border-neutral-300 text-sm placeholder:text-neutral-400 focus:outline-none focus:ring-2 focus:ring-neutral-300" />
|
||
|
|
<button type="submit" className="h-8 px-3 rounded-md bg-neutral-900 text-white text-sm hover:bg-neutral-800">검색</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export default BoardToolbar;
|
||
|
|
|
||
|
|
|