Skip to content

Commit a534460

Browse files
authored
Merge pull request #30 from nguswjd/feat/mainpage
feat/mainpage
2 parents 3cb9353 + b3429e9 commit a534460

File tree

5 files changed

+177
-26
lines changed

5 files changed

+177
-26
lines changed

src/App.tsx

Lines changed: 145 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,161 @@
11
import './App.css';
22
import { Routes, Route, useNavigate } from 'react-router';
3-
import Counter from './components/Counter';
4-
import { Button } from './components/ui/button';
53
import { Signup } from './auth/sign-up';
6-
import Aside from './components/aside/aside';
74
import ShopArtistNotice from './page/shop-artist-notice';
5+
import { ChevronDown, ChevronRight, ChevronLeft } from 'lucide-react';
6+
import { useState } from 'react';
7+
import { Button } from './components/ui/button';
8+
9+
import KakaoLogo from './assets/kakao-logo.svg';
810

911
function MainPage() {
1012
const navigate = useNavigate();
1113

14+
const [currentNoticePage, setCurrentNoticePage] = useState(1);
15+
const noticesPerPage = 5;
16+
17+
const regions = [
18+
{ value: 'seoul', label: '서울' },
19+
{ value: 'busan', label: '부산' },
20+
{ value: 'incheon', label: '인천' },
21+
];
22+
23+
const allNotices = [
24+
{ category: '공지', content: '10/20-10/22 KTX 반값!' },
25+
{ category: '부산', content: '황금연휴, ‘공짜’로 부산가기 이벤트!' },
26+
{ category: '이벤트', content: '선착순 EVENT 케이팝데몬헌터스 굿즈' },
27+
{ category: '축제', content: '단풍의 계절 10월 “청도 단풍 축제”' },
28+
{
29+
category: '문화공연',
30+
content: '광안리 oo만명 인파 드론이 수놓은 한글날',
31+
},
32+
];
33+
34+
const totalNoticePages = Math.ceil(allNotices.length / noticesPerPage);
35+
36+
const currentNotices = allNotices.slice(
37+
(currentNoticePage - 1) * noticesPerPage,
38+
currentNoticePage * noticesPerPage
39+
);
40+
1241
const handleSignupClick = () => {
1342
navigate('/signup');
1443
};
1544

45+
const handleNoticePrevPage = () => {
46+
if (currentNoticePage > 1) {
47+
setCurrentNoticePage(currentNoticePage - 1);
48+
}
49+
};
50+
51+
const handleNoticeNextPage = () => {
52+
if (currentNoticePage < totalNoticePages) {
53+
setCurrentNoticePage(currentNoticePage + 1);
54+
}
55+
};
56+
1657
return (
17-
<div className="flex min-h-screen items-center justify-center bg-gray-100">
18-
<Aside />
19-
<div className="rounded-lg bg-white p-8 shadow-md">
20-
<h1 className="mb-8 text-center text-3xl font-bold text-gray-800">
21-
moduLapProject
22-
</h1>
23-
<Counter />
24-
<Button
25-
variant="primary"
26-
label="회원가입"
27-
onClick={handleSignupClick}
28-
/>
58+
<div className="flex min-h-screen w-[120rem] items-center justify-center gap-3">
59+
<div className="flex gap-3">
60+
<div className="flex w-[62.68rem] flex-col gap-3">
61+
<section className="flex h-[20.93rem] w-full items-center justify-center rounded-sm border border-gray-300">
62+
<h2>캐러셀 배너</h2>
63+
</section>
64+
65+
<section className="grid h-[43rem] w-full grid-cols-2 gap-3">
66+
<h2 className="hidden">포스트</h2>
67+
<div className="rounded-sm border border-gray-300">포스트</div>
68+
<div className="rounded-sm border border-gray-300">포스트</div>
69+
<div className="rounded-sm border border-gray-300">포스트</div>
70+
<div className="rounded-sm border border-gray-300">포스트</div>
71+
</section>
72+
</div>
73+
74+
<aside className="flex w-[17.125rem] flex-col gap-3">
75+
<section className="flex h-[15.0625rem] w-full flex-col justify-center gap-6 rounded-sm border border-gray-300">
76+
<h2 className="hidden">회원가입</h2>
77+
<div className="flex flex-col items-center gap-5">
78+
<p className="text-center text-base font-semibold">
79+
지금 가입해서{' '}
80+
<span className="font-extrabold">전국의 소품샵</span><br />
81+
<span className="font-extrabold">한눈에 확인</span>하세요!
82+
</p>
83+
84+
<div className="relative inline-block rounded-[12.5px] border border-gray-200 bg-white px-3 py-1 shadow-[0_1px_0_0_rgba(0,0,0,0.25)] after:absolute after:left-1/2 after:top-full after:-translate-x-1/2 after:border-8 after:border-transparent after:border-t-white after:drop-shadow-[0_1px_0_rgba(0,0,0,0.25)]">
85+
<p className="text-xs font-medium">
86+
<span className="font-semibold">3초안에</span> 빠른 회원가입
87+
</p>
88+
</div>
89+
90+
<button
91+
className="flex w-[13.25rem] items-center justify-center gap-2 rounded-sm bg-[#FEE500] py-2 text-xs font-bold"
92+
onClick={handleSignupClick}
93+
>
94+
카카오로 시작하기
95+
<img src={KakaoLogo} alt="dear objet 로고" />
96+
</button>
97+
</div>
98+
</section>
99+
100+
<section className="flex flex-col gap-3">
101+
<h2 className="hidden">축제</h2>
102+
<div className="flex items-center rounded-sm border border-gray-300 px-7 py-2">
103+
<p className="pr-8 text-xs">지역</p>
104+
<div className="relative">
105+
<select className="appearance-none pr-6 text-sm font-extrabold">
106+
{regions.map((region) => (
107+
<option key={region.value} value={region.value}>
108+
{region.label}
109+
</option>
110+
))}
111+
</select>
112+
113+
<ChevronDown className="pointer-events-none absolute right-0 top-1/2 h-4 w-4 -translate-y-1/2" />
114+
</div>
115+
</div>
116+
117+
<div className="h-[15.75rem] bg-gray-200"></div>
118+
119+
<div className="flex gap-10 self-center">
120+
<Button variant="icon" icon={<ChevronLeft />} />
121+
<Button variant="icon" icon={<ChevronRight />} />
122+
</div>
123+
</section>
124+
125+
<section className="flex flex-col gap-3">
126+
<h2>공지&이벤트</h2>
127+
<div className="w-full rounded-sm border border-gray-300 p-3">
128+
<div className="flex flex-col gap-3">
129+
{currentNotices.map((notice, index) => (
130+
<div key={index} className="flex text-[0.625rem] font-normal">
131+
<span className="w-12 shrink-0 text-center">
132+
{notice.category}
133+
</span>
134+
<span className="truncate text-left">{notice.content}</span>
135+
</div>
136+
))}
137+
</div>
138+
</div>
139+
140+
<div
141+
className="relative flex items-center gap-10 self-center after:absolute after:left-1/2 after:top-1/2 after:-translate-x-1/2 after:-translate-y-1/2 after:text-sm after:content-[attr(data-page)]"
142+
data-page={`${currentNoticePage}/${totalNoticePages}`}
143+
>
144+
<Button
145+
variant="icon"
146+
icon={<ChevronLeft />}
147+
onClick={handleNoticePrevPage}
148+
disabled={currentNoticePage === 1}
149+
/>
150+
<Button
151+
variant="icon"
152+
icon={<ChevronRight />}
153+
onClick={handleNoticeNextPage}
154+
disabled={currentNoticePage === totalNoticePages}
155+
/>
156+
</div>
157+
</section>
158+
</aside>
29159
</div>
30160
</div>
31161
);

src/assets/kakao-logo.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type { Meta, StoryObj } from '@storybook/react-vite';
2-
32
import { fn } from 'storybook/test';
4-
53
import { Button } from './button';
4+
import type { ButtonProps } from './button';
5+
import { ChevronDown } from 'lucide-react';
66

77
const meta = {
88
title: 'Example/Button',
@@ -14,7 +14,10 @@ const meta = {
1414
argTypes: {
1515
variant: {
1616
control: { type: 'select' },
17-
options: ['primary', 'secondaryLight', 'secondaryDark'],
17+
options: ['primary', 'secondaryLight', 'secondaryDark', 'icon'],
18+
},
19+
disabled: {
20+
control: { type: 'boolean' },
1821
},
1922
},
2023
args: { onClick: fn() },
@@ -29,3 +32,12 @@ export const Primary: Story = {
2932
label: 'Button',
3033
},
3134
};
35+
36+
export const Icon: Story = {
37+
render: (args: ButtonProps) => {
38+
return <Button {...args} icon={<ChevronDown />} />;
39+
},
40+
args: {
41+
variant: 'icon',
42+
},
43+
};

src/components/ui/button.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1+
import type { ReactNode } from 'react';
2+
13
export interface ButtonProps {
2-
variant?: 'primary' | 'secondaryLight' | 'secondaryDark';
4+
variant?: 'primary' | 'secondaryLight' | 'secondaryDark' | 'icon';
35
size?: 'small' | 'medium' | 'large';
4-
label: string;
6+
label?: string;
7+
icon?: ReactNode;
58
onClick?: () => void;
69
className?: string;
10+
disabled?: boolean;
711
}
812

913
export const Button = ({
1014
variant = 'primary',
1115
size = 'medium',
1216
label,
17+
icon,
1318
onClick,
1419
className = '',
1520
...props
@@ -27,16 +32,17 @@ export const Button = ({
2732
'border-gray-900 hover:bg-gray-100 hover:border-gray-900 text-gray-900 rounded active:bg-gray-200 active:border-gray-900 disabled:bg-white disabled:border-gray-300 disabled:text-gray-300',
2833
secondaryDark:
2934
'bg-gray-900 border-gray-900 hover:border-gray-900 hover:border-gray-700 text-white rounded active:bg-black active:border-gray-900 disabled:bg-gray-200 disabled:border-gray-200 disabled:text-gray-500',
35+
icon: 'disabled:text-gray-200 text-black',
3036
};
3137

3238
return (
3339
<button
3440
type="button"
35-
className={` ${sizeClasses[size]} ${variantClasses[variant]} ${className}`}
41+
className={`${sizeClasses[size]} ${variantClasses[variant]} ${className}`}
3642
onClick={onClick}
3743
{...props}
3844
>
39-
{label}
45+
{icon || label}
4046
</button>
4147
);
4248
};

src/index.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ h1 {
3939
line-height: 1.1;
4040
}
4141

42-
button {
42+
/* button {
4343
border-radius: 8px;
4444
border: 1px solid transparent;
4545
padding: 0.6em 1.2em;
@@ -56,7 +56,7 @@ button:hover {
5656
button:focus,
5757
button:focus-visible {
5858
outline: 4px auto -webkit-focus-ring-color;
59-
}
59+
} */
6060

6161
@media (prefers-color-scheme: light) {
6262
:root {
@@ -66,7 +66,7 @@ button:focus-visible {
6666
a:hover {
6767
color: #747bff;
6868
}
69-
button {
69+
/* button {
7070
background-color: #f9f9f9;
71-
}
71+
} */
7272
}

0 commit comments

Comments
 (0)