diff --git a/app/(main)/meetup/list/page.tsx b/app/(main)/meetup/list/page.tsx
index 9b4fdae4..2f75c196 100644
--- a/app/(main)/meetup/list/page.tsx
+++ b/app/(main)/meetup/list/page.tsx
@@ -1,13 +1,14 @@
import { Suspense } from "react";
import { Metadata } from "next";
+import { cn } from "@/utils/cn";
import Container from "@/components/layout/Container";
+import QueryErrorBoundary from "@/components/common/QueryErrorBoundary";
import Banner from "@/features/meetup/list/components/Banner";
+import { MeetupListScrollProvider } from "@/features/meetup/list/providers/MeetupListScrollProvider";
import ListFilters from "@/features/meetup/list/components/ListFilters";
-import CreateOpenButton from "@/features/meetup/create/components/CreateOpenButton";
+import ListFiltersSkeleton from "@/features/meetup/list/components/ListFilters/ListFiltersSkeleton";
import MeetupCardList from "@/features/meetup/list/components/MeetupCardList";
-import { MeetupListScrollProvider } from "@/features/meetup/list/providers/MeetupListScrollProvider";
-import QueryErrorBoundary from "@/components/common/QueryErrorBoundary";
-import { cn } from "@/utils/cn";
+import CreateOpenButton from "@/features/meetup/create/components/CreateOpenButton";
export const metadata: Metadata = {
title: "모임 찾기",
@@ -17,6 +18,8 @@ export const metadata: Metadata = {
},
};
+const size = 10;
+
export default function MeetupListPage() {
return (
@@ -26,14 +29,12 @@ export default function MeetupListPage() {
"md:min-h-[calc(100vh-88px)] md:gap-y-4 md:p-6 lg:gap-y-6 lg:pt-7",
)}>
-
-
-
-
-
-
-
+ }>
+
+
+
+
@@ -41,3 +42,5 @@ export default function MeetupListPage() {
);
}
+
+const ListFiltersStyle = "mx-0 bg-gray-50 px-6 py-2 md:-mx-4 md:px-6";
diff --git a/features/meetup/list/components/ListFilters/ListFiltersSkeleton.tsx b/features/meetup/list/components/ListFilters/ListFiltersSkeleton.tsx
new file mode 100644
index 00000000..5fe2ba65
--- /dev/null
+++ b/features/meetup/list/components/ListFilters/ListFiltersSkeleton.tsx
@@ -0,0 +1,88 @@
+"use client";
+
+import { useCategoryStore } from "@/store/category.store";
+import { cn } from "@/utils/cn";
+
+interface ListFiltersSkeletonProps {
+ className?: string;
+}
+
+export default function ListFiltersSkeleton({ className }: ListFiltersSkeletonProps) {
+ const { categories } = useCategoryStore();
+ const typeTabCount = categories.length + 1;
+
+ return (
+
+ );
+}
+
+const tabScrollRowClass =
+ "overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden";
+const tabSkeletonShape = "box-border h-9 shrink-0 rounded-[0.875rem] px-4 md:h-10 md:rounded-2xl";
+const dropdownTriggerShape = "h-6 shrink-0 rounded-lg md:h-8";
+
+function TabRowSkeleton({ typeTabCount }: { typeTabCount: number }) {
+ return (
+
+ {/* 검색 토글 */}
+ -
+
+
+ {/* 타입 탭 */}
+ {Array.from({ length: typeTabCount }, (_, i) => (
+ -
+
+
+ ))}
+
+ );
+}
+
+function KeywordAreaSkeleton() {
+ return (
+
+ );
+}
+
+function DropdownRowSkeleton() {
+ return (
+
+ {/* 모든 드롭다운 스켈레톤: 동일한 폭으로 통일 */}
+ {Array.from({ length: 4 }).map((_, i) => (
+
+ ))}
+
+ );
+}
diff --git a/features/meetup/list/components/MeetupCardItems/index.tsx b/features/meetup/list/components/MeetupCardItems/index.tsx
index 587d16a2..0a140c90 100644
--- a/features/meetup/list/components/MeetupCardItems/index.tsx
+++ b/features/meetup/list/components/MeetupCardItems/index.tsx
@@ -13,6 +13,7 @@ import Empty from "@/components/ui/Empty";
import JoinModal from "../JoinModal";
interface MeetupCardItemsProps {
+ /** 모임 목록 쿼리 */
query: UseInfiniteQueryResult>;
}
@@ -59,15 +60,18 @@ interface MeetupCardLoadedItemsProps {
data: MeetupItem[] | undefined;
setSelectedData: (data: MeetupItemSelected) => void;
openModalFn: () => void;
+ className?: string;
}
function MeetupCardLoadedItems({ data, setSelectedData, openModalFn }: MeetupCardLoadedItemsProps) {
if (data?.length === 0) {
return (
-
- 아직 모임이 없어요
-
- 지금 바로 모임을 만들어보세요!
-
+
+
+ 아직 모임이 없어요
+
+ 지금 바로 모임을 만들어보세요!
+
+
);
}
return (
diff --git a/features/meetup/list/components/MeetupCardList/MeetupCardListSkeleton.tsx b/features/meetup/list/components/MeetupCardList/MeetupCardListSkeleton.tsx
new file mode 100644
index 00000000..89e49f52
--- /dev/null
+++ b/features/meetup/list/components/MeetupCardList/MeetupCardListSkeleton.tsx
@@ -0,0 +1,11 @@
+"use client";
+
+import GroupCard from "@/components/ui/GroupCard";
+
+export default function MeetupCardListSkeleton({ size }: { size: number }) {
+ return Array.from({ length: size }).map((_, i) => (
+
+
+
+ ));
+}
diff --git a/features/meetup/list/components/MeetupCardList/index.tsx b/features/meetup/list/components/MeetupCardList/index.tsx
index 8184f6be..2f32637c 100644
--- a/features/meetup/list/components/MeetupCardList/index.tsx
+++ b/features/meetup/list/components/MeetupCardList/index.tsx
@@ -1,16 +1,14 @@
"use client";
-import GroupCard from "@/components/ui/GroupCard";
import { useGetMeetups } from "@/features/meetup/queries";
-import MeetupCardItems from "../MeetupCardItems";
import { cn } from "@/utils/cn";
-
-const size = 10;
+import MeetupCardItems from "../MeetupCardItems";
+import MeetupCardListSkeleton from "./MeetupCardListSkeleton";
interface MeetupCardListProps {
- className?: string;
+ size: number;
}
-export default function MeetupCardList({ className }: MeetupCardListProps) {
+export default function MeetupCardList({ size }: MeetupCardListProps) {
const query = useGetMeetups(size);
const isRefetching = query.isFetching && !query.isFetchingNextPage && !query.isPending;
@@ -18,22 +16,11 @@ export default function MeetupCardList({ className }: MeetupCardListProps) {
- {query.isPending ? (
-
- ) : (
-
- )}
+ {query.isPending ? : }
);
}
-
-function MeetupCardSkeletonItems({ size }: { size: number }) {
- return Array.from({ length: size }).map((_, i) => (
-
-
-
- ));
-}