|
1 | 1 | import './App.css'; |
2 | 2 | import { Routes, Route, useNavigate } from 'react-router'; |
3 | | -import Counter from './components/Counter'; |
4 | | -import { Button } from './components/ui/button'; |
5 | 3 | import { Signup } from './auth/sign-up'; |
6 | | -import Aside from './components/aside/aside'; |
7 | 4 | 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'; |
8 | 10 |
|
9 | 11 | function MainPage() { |
10 | 12 | const navigate = useNavigate(); |
11 | 13 |
|
| 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 | + |
12 | 41 | const handleSignupClick = () => { |
13 | 42 | navigate('/signup'); |
14 | 43 | }; |
15 | 44 |
|
| 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 | + |
16 | 57 | 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> |
29 | 159 | </div> |
30 | 160 | </div> |
31 | 161 | ); |
|
0 commit comments