Skip to content

Commit 684f132

Browse files
committed
feat: 알바폼 리스트 스토리북 추가 및 레이아웃 수정
1 parent b547f0f commit 684f132

File tree

12 files changed

+511
-40
lines changed

12 files changed

+511
-40
lines changed

.storybook/main.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ interface StorybookConfig extends BaseStorybookConfig {
55
}
66

77
const config: StorybookConfig = {
8-
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
9-
addons: ["@storybook/addon-links", "@storybook/addon-essentials", "@storybook/addon-interactions"],
8+
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
9+
addons: [
10+
"@storybook/addon-links",
11+
"@storybook/addon-essentials",
12+
"@storybook/addon-onboarding",
13+
"@storybook/addon-interactions",
14+
"@storybook/addon-styling",
15+
],
1016
framework: {
1117
name: "@storybook/nextjs",
1218
options: {},
@@ -20,6 +26,9 @@ const config: StorybookConfig = {
2026
};
2127
return config;
2228
},
29+
docs: {
30+
autodocs: "tag",
31+
},
2332
};
2433

2534
export default config;

package-lock.json

Lines changed: 33 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"@chromatic-com/storybook": "^3.2.2",
4040
"@storybook/addon-essentials": "^8.4.4",
4141
"@storybook/addon-interactions": "^8.4.4",
42+
"@storybook/addon-links": "^8.4.7",
4243
"@storybook/addon-onboarding": "^8.4.4",
4344
"@storybook/addon-styling": "^2.0.0",
4445
"@storybook/blocks": "^8.4.4",

src/app/(pages)/albaList/components/SortSection.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@ export default function SortSection() {
2626
};
2727

2828
return (
29-
<div className="fixed right-6 top-[180px] z-10 md:right-28 md:top-[200px] lg:right-8">
30-
<FilterDropdown
31-
options={SORT_OPTIONS.map((option) => option.label)}
32-
className="!w-28 md:!w-40"
33-
initialValue={currentLabel}
34-
onChange={handleSortChange}
35-
/>
36-
</div>
29+
<FilterDropdown
30+
options={SORT_OPTIONS.map((option) => option.label)}
31+
className="!w-28 md:!w-40"
32+
initialValue={currentLabel}
33+
onChange={handleSortChange}
34+
/>
3735
);
3836
}

src/app/(pages)/albaList/layout.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import React, { Suspense } from "react";
2-
import SortSection from "./components/SortSection";
32

43
export default function AlbaListLayout({ children }: { children: React.ReactNode }) {
54
return (
6-
<div className="mx-auto max-w-screen-lg px-4 py-8">
7-
<SortSection />
8-
5+
<div className="mx-auto max-w-screen-2xl px-4 py-8">
96
<Suspense
107
fallback={
118
<div className="flex h-[calc(100vh-200px)] items-center justify-center">

src/app/(pages)/albaList/page.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { useForms } from "@/hooks/queries/form/useForms";
66
import FilterDropdown from "@/app/components/button/dropdown/FilterDropdown";
77
import { filterRecruitingOptions } from "@/constants/filterOptions";
88
import { useRouter, usePathname, useSearchParams } from "next/navigation";
9+
import SortSection from "./components/SortSection";
10+
import AlbaListItem from "@/app/components/card/cardList/AlbaListItem";
911

1012
const FORMS_PER_PAGE = 10;
1113

@@ -29,7 +31,7 @@ export default function AlbaList() {
2931
// 무한 스크롤을 위한 Intersection Observer 설정
3032
const { ref, inView } = useInView({
3133
threshold: 0.1,
32-
triggerOnce: true,
34+
triggerOnce: false,
3335
rootMargin: "100px",
3436
});
3537

@@ -88,13 +90,14 @@ export default function AlbaList() {
8890
return (
8991
<div className="space-y-4">
9092
{/* 필터 드롭다운 섹션 */}
91-
<div className="border-b border-grayscale-100">
92-
<div className="flex items-center gap-2 py-4">
93+
<div className="border-b border-grayscale-100 bg-white">
94+
<div className="mx-auto flex max-w-screen-2xl items-center justify-between gap-2 px-4 py-4 md:px-6 lg:px-8">
9395
<FilterDropdown
9496
options={filterRecruitingOptions.map((option) => option.label)}
9597
initialValue={getInitialRecruitingValue(isRecruiting)}
9698
onChange={handleRecruitingFilter}
9799
/>
100+
<SortSection />
98101
</div>
99102
</div>
100103

@@ -105,22 +108,17 @@ export default function AlbaList() {
105108
</div>
106109
) : (
107110
<>
108-
{data?.pages.map((page) => (
109-
<React.Fragment key={page.nextCursor}>
110-
{page.data.map((form) => (
111-
<div key={form.id} className="rounded-lg border p-4 transition-all hover:border-primary-orange-200">
112-
<h3 className="font-bold">{form.title}</h3>
113-
<div className="mt-2 text-sm text-grayscale-500">
114-
<span>지원자 {form.applyCount}</span>
115-
<span className="mx-2"></span>
116-
<span>스크랩 {form.scrapCount}</span>
117-
<span className="mx-2"></span>
118-
<span>마감 {new Date(form.recruitmentEndDate).toLocaleDateString()}</span>
111+
<div className="mx-auto grid max-w-screen-2xl grid-cols-1 gap-8 px-4 md:px-6 lg:grid-cols-2 lg:px-8 2xl:grid-cols-3 2xl:gap-12">
112+
{data?.pages.map((page) => (
113+
<React.Fragment key={page.nextCursor}>
114+
{page.data.map((form) => (
115+
<div key={form.id} className="w-full">
116+
<AlbaListItem {...form} />
119117
</div>
120-
</div>
121-
))}
122-
</React.Fragment>
123-
))}
118+
))}
119+
</React.Fragment>
120+
))}
121+
</div>
124122

125123
{/* 무한 스크롤 트리거 영역 */}
126124
<div ref={ref} className="h-4 w-full">

src/app/components/card/cardList/AlbaListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ const AlbaListItem = ({
8282
};
8383

8484
return (
85-
<div className="relative h-auto w-full overflow-hidden rounded-xl border border-grayscale-200 bg-white shadow-md transition-transform duration-300 hover:scale-[1.02] sm:h-[390px] sm:w-[327px] md:h-[536px] md:w-[477px]">
85+
<div className="relative h-[390px] w-[327px] overflow-hidden rounded-xl border border-grayscale-200 bg-white shadow-md transition-transform duration-300 hover:scale-[1.02] lg:h-[536px] lg:w-[477px]">
8686
{/* 이미지 슬라이더 영역 */}
8787
<div className="relative h-[150px] overflow-hidden rounded-t-xl sm:h-[220px] md:h-[310px]">
8888
{/* 현재 이미지 */}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import AlbaList from "./page";
3+
import AlbaListLayout from "@/app/(pages)/albaList/layout";
4+
5+
const meta = {
6+
title: "Design System/Pages/AlbaList",
7+
component: AlbaList,
8+
parameters: {
9+
layout: "fullscreen",
10+
nextjs: {
11+
appDirectory: true,
12+
navigation: {
13+
pathname: "/albaList",
14+
query: {
15+
isRecruiting: "true",
16+
},
17+
},
18+
},
19+
},
20+
decorators: [
21+
(Story: React.ComponentType) => (
22+
<AlbaListLayout>
23+
<Story />
24+
</AlbaListLayout>
25+
),
26+
],
27+
} satisfies Meta<typeof AlbaList>;
28+
29+
export default meta;
30+
type Story = StoryObj<typeof AlbaList>;
31+
32+
// 기본 목록 페이지
33+
export const Default: Story = {};
34+
35+
// 모바일 뷰
36+
export const Mobile: Story = {
37+
parameters: {
38+
viewport: {
39+
defaultViewport: "mobile",
40+
},
41+
},
42+
};
43+
44+
// 태블릿 뷰
45+
export const Tablet: Story = {
46+
parameters: {
47+
viewport: {
48+
defaultViewport: "tablet",
49+
},
50+
},
51+
};
52+
53+
// 데스크톱 뷰
54+
export const Desktop: Story = {
55+
parameters: {
56+
viewport: {
57+
defaultViewport: "desktop",
58+
},
59+
},
60+
};
61+
62+
// 로딩 상태
63+
export const Loading: Story = {
64+
parameters: {
65+
mockData: {
66+
loading: true,
67+
},
68+
},
69+
};
70+
71+
// 빈 상태
72+
export const Empty: Story = {
73+
parameters: {
74+
mockData: {
75+
empty: true,
76+
},
77+
},
78+
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import React from "react";
3+
import AlbaListLayout from "@/app/(pages)/albaList/layout";
4+
import { StoryComponent } from "./page.stories";
5+
6+
const meta = {
7+
title: "Design System/Pages/AlbaList/Layout",
8+
component: AlbaListLayout,
9+
parameters: {
10+
layout: "fullscreen",
11+
nextjs: {
12+
appDirectory: true,
13+
},
14+
},
15+
} satisfies Meta<typeof AlbaListLayout>;
16+
17+
export default meta;
18+
type Story = StoryObj<typeof AlbaListLayout>;
19+
20+
// 기본 레이아웃 (데스크톱)
21+
export const Desktop: Story = {
22+
render: () => <StoryComponent />,
23+
parameters: {
24+
viewport: {
25+
defaultViewport: "desktop",
26+
},
27+
},
28+
};
29+
30+
// 태블릿 레이아웃
31+
export const Tablet: Story = {
32+
render: () => <StoryComponent />,
33+
parameters: {
34+
viewport: {
35+
defaultViewport: "tablet",
36+
},
37+
},
38+
};
39+
40+
// 모바일 레이아웃
41+
export const Mobile: Story = {
42+
render: () => <StoryComponent />,
43+
parameters: {
44+
viewport: {
45+
defaultViewport: "mobile1",
46+
},
47+
},
48+
};
49+
50+
// 로딩 상태
51+
export const Loading: Story = {
52+
render: () => (
53+
<div className="mx-auto max-w-screen-2xl px-4 py-8">
54+
<div className="flex h-[calc(100vh-200px)] items-center justify-center">
55+
<div>로딩 중...</div>
56+
</div>
57+
</div>
58+
),
59+
};
60+
61+
// 빈 상태
62+
export const Empty: Story = {
63+
render: () => (
64+
<div className="mx-auto max-w-screen-2xl px-4 py-8">
65+
<div className="flex h-[calc(100vh-200px)] items-center justify-center">
66+
<p className="text-grayscale-500">등록된 알바 공고가 없습니다.</p>
67+
</div>
68+
</div>
69+
),
70+
};

0 commit comments

Comments
 (0)