@@ -51,43 +82,58 @@ export default function ScrapsSection() {
);
}
- // 데이터가 없는 경우 처리
- if (!data?.pages[0]?.data?.length) {
- return (
-
+ {/* 필터 드롭다운 섹션 */}
+
+
+ option.label)}
+ initialValue={getInitialPublicValue(filterBy.isPublic)}
+ onChange={handlePublicFilter}
+ />
+ option.label)}
+ initialValue={getInitialRecruitingValue(filterBy.isRecruiting)}
+ onChange={handleRecruitingFilter}
+ />
+
+
+
{/* 스크랩 목록 렌더링 */}
- {data.pages.map((page, index) => (
-
- {page.data.map((scrap: FormListType) => (
-
-
{scrap.title}
-
- 지원자 {scrap.applyCount}명
- •
- 스크랩 {scrap.scrapCount}명
- •
- 마감 {new Date(scrap.recruitmentEndDate).toLocaleDateString()}
-
-
+ {!data?.pages[0]?.data?.length ? (
+
+ ) : (
+ <>
+ {data.pages.map((page, index) => (
+
+ {page.data.map((scrap: FormListType) => (
+
+
{scrap.title}
+
+ 지원자 {scrap.applyCount}명
+ •
+ 스크랩 {scrap.scrapCount}명
+ •
+ 마감 {new Date(scrap.recruitmentEndDate).toLocaleDateString()}
+
+
+ ))}
+
))}
-
- ))}
- {/* 무한 스크롤 트리거 영역 */}
-
- {isFetchingNextPage && (
-
-
+ {/* 무한 스크롤 트리거 영역 */}
+
+ {isFetchingNextPage && (
+
+ )}
- )}
-
+ >
+ )}
);
}
diff --git a/src/app/(pages)/mypage/layout.tsx b/src/app/(pages)/mypage/layout.tsx
index 3c5db867..c493c6b1 100644
--- a/src/app/(pages)/mypage/layout.tsx
+++ b/src/app/(pages)/mypage/layout.tsx
@@ -8,7 +8,7 @@ interface MypageLayoutProps {
export default function MypageLayout({ children }: MypageLayoutProps) {
return (
-
+
로딩 중...
}>
{children}
diff --git a/src/app/api/users/me/scrap/route.ts b/src/app/api/users/me/scrap/route.ts
index 275c60cd..1879b26a 100644
--- a/src/app/api/users/me/scrap/route.ts
+++ b/src/app/api/users/me/scrap/route.ts
@@ -15,14 +15,24 @@ export async function GET(request: Request) {
// URL 쿼리 파라미터 파싱
const { searchParams } = new URL(request.url);
- const params = {
- cursor: searchParams.get("cursor"), // 페이지네이션 커서
- limit: searchParams.get("limit"), // 한 페이지당 항목 수
- orderBy: searchParams.get("orderBy"), // 정렬 기준
- isPublic: searchParams.get("isPublic"), // 공개 여부
- isRecruiting: searchParams.get("isRecruiting"), // 모집 중 여부
+ const params: Record
= {
+ cursor: searchParams.get("cursor"),
+ limit: searchParams.get("limit"),
+ orderBy: searchParams.get("orderBy"),
};
+ // isPublic과 isRecruiting은 값이 있을 때만 추가
+ const isPublic = searchParams.get("isPublic");
+ const isRecruiting = searchParams.get("isRecruiting");
+
+ if (isPublic !== null && isPublic !== "null") {
+ params.isPublic = isPublic;
+ }
+
+ if (isRecruiting !== null && isRecruiting !== "null") {
+ params.isRecruiting = isRecruiting;
+ }
+
// 스크랩 목록 조회 요청
const response = await apiClient.get("/users/me/scrap", {
headers: {
diff --git a/src/constants/filterOptions.ts b/src/constants/filterOptions.ts
new file mode 100644
index 00000000..911cd296
--- /dev/null
+++ b/src/constants/filterOptions.ts
@@ -0,0 +1,11 @@
+export const filterPublicOptions = [
+ { label: "전체", value: null },
+ { label: "공개", value: true },
+ { label: "비공개", value: false },
+] as const;
+
+export const filterRecruitingOptions = [
+ { label: "전체", value: null },
+ { label: "모집중", value: true },
+ { label: "모집마감", value: false },
+] as const;
diff --git a/src/store/filterStore.ts b/src/store/filterStore.ts
new file mode 100644
index 00000000..051f5cde
--- /dev/null
+++ b/src/store/filterStore.ts
@@ -0,0 +1,25 @@
+import { create } from "zustand";
+
+type FilterType = "isPublic" | "isRecruiting";
+
+interface FilterState {
+ filterBy: {
+ isPublic: boolean;
+ isRecruiting: boolean;
+ };
+ setFilterBy: (filterType: FilterType, value: string) => void;
+}
+
+export const useFilterStore = create((set) => ({
+ filterBy: {
+ isPublic: true,
+ isRecruiting: true,
+ },
+ setFilterBy: (filterType, value) =>
+ set((state) => ({
+ filterBy: {
+ ...state.filterBy,
+ [filterType]: value,
+ },
+ })),
+}));