From 16b618d8cee8169b35a86b841ccb44ae497a0315 Mon Sep 17 00:00:00 2001 From: Minji Kim <68258295+minzee09@users.noreply.github.com> Date: Fri, 21 Feb 2025 04:10:47 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[DEPLOY]=205=EC=B0=A8=20=EB=B0=B0=ED=8F=AC?= =?UTF-8?q?=20(#101)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * โœจ feat: MainPage Banner UI ๊ตฌํ˜„ * ๐Ÿ’„ UI: Banner padding ์ˆ˜์ • # 11 * โœจ feat: QuizBox ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * โœจ feat: SearchBar ๊ตฌํ˜„ #11 * โœจ feat: Categories ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * ๐Ÿ”ง config: Font Awesome ์„ค์น˜ #11 * ๐Ÿ’„ UI: categories ์•„๋ž˜ ํ™”์‚ดํ‘œ ์ถ”๊ฐ€ #11 * โœจ feat : TipsSection ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * โœจ feat: LoginPage Title&Input UI ๊ตฌํ˜„ #10 * โœจ feat: LoginPage LoginOptions UI ๊ตฌํ˜„ #10 * โœจ feat: LoginPage LoginButton UI ๊ตฌํ˜„ #10 * โ™ป๏ธ refactor: LoginPage Title component #10 * โ™ป๏ธ refactor: LoginPage Title component #10 * โ™ป๏ธ refactor: LoginPage ButtonBox component #10 * โ™ป๏ธ refactor: LoginPage InputForm component #10 * ๐Ÿ’„ UI : TipsSectionTopFive ์ค‘๋ณต ์‚ญ์ œ #11 * ๐Ÿ’„ UI : Card Component ๋ถ„๋ฆฌ ์ž‘์—… #11 * ๐Ÿ’„ UI : SearchBar/ Card ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #11 * ๐Ÿ”ง config: CI ๊ฒฝ๋กœ ์ˆ˜์ • #7 * ๐Ÿ”ง config: cwd ์ถ”๊ฐ€ #7 * ๐Ÿ”ง config: ๋ผ์šฐํŒ… ๋™์ž‘ ์œ„ํ•œ ํŒŒ์ผ ์ถ”๊ฐ€ #7 * ๐Ÿ’„ UI: LoginPage KakaoLogin Button ์ˆ˜์ • #10 * ๐Ÿ’„ UI: LoginPage UI์‚ฌ์ด์ฆˆ ์ถ•์†Œ #10 * ๐Ÿ’„ UI: LoginPage UI์‚ฌ์ด์ฆˆ ํ™•๋Œ€ (Figma Size) #10 * โœจ feat: add MyPage router #16 * โœจ feat: MyPage Title&์ƒ๋‹จ์นด๋“œ ๊ตฌํ˜„ํ˜„ #16 * โœจ feat: MyPage ํ”„๋กœํ•„ ๋ณ€๊ฒฝ ๋ฒ„ํŠผ ์ถ”๊ฐ€๊ฐ€ #16 * ๐Ÿ”ง config: eslint ๊ทœ์น™ ์ œ๊ฑฐ #12 * ๐Ÿ“ฆ package: add react-icons #12 * ๐ŸŽจ styles: update reset.css file #12 * ๐Ÿ’„ UI: add logo image #12 * โœจ feat: ํ—ค๋” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #12 * โœจ feat: ํ‘ธํ„ฐ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #12 * ๐Ÿ’„ UI: ํ—ค๋” ํ‘ธํ„ฐ ๋ ˆ์ด์•„์›ƒ ์ถ”๊ฐ€ #12 * โœจ feat: MyPage ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ถ”๊ฐ€ & ์นด๋“œ ์ปดํฌ๋„ŒํŠธ #16 * โœ๏ธ typo: MyPage GoodTip->RecnetGoodTip์œผ๋กœ ์ˆ˜์ •์ • #16 * โœจ feat: MyPage Best ๊ฟ€ํŒ ์„ ์ • ํšŸ์ˆ˜ & ๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ ์ปดํฌ๋„ŒํŠธ #16 * โ™ป๏ธ refactor: MyPage ProfileSection ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage RecentTips ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage dummyData ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage BestInterest ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage ์ด์Šˆ๋ฒˆํ˜ธ ์ˆ˜์ •์ • #16 * ๐Ÿ’„ UI: MyPage ์ปดํฌ๋„ŒํŠธ ์œ„์น˜ ์ˆ˜์ • #16 * ๐Ÿ“ฆ package: add framer-motion #12 * ๐ŸŽจ style: ์„ ๋ฌผ์ƒ์ž, ํŠธ๋กœํ”ผ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #12 * โœจ feat: ์Šคํฌ๋กค ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ›… ์ถ”๊ฐ€ #12 * โœจ feat: add LandingPage #12 * ๐Ÿ’„ UI : Card CSS ์ค‘๋ณต ์ œ๊ฑฐ #19 * ๐Ÿ’„ UI : dummy Image ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI : max-width -> min-width ์ˆ˜์ • #19 * ๐Ÿ’„ UI : SearchSection ์ปดํฌ๋„ŒํŠธ ์„ธ๋ถ„ํ™” ๋ฐ CSS ์ˆ˜์ • #19 * ๐Ÿ’„ UI : TipSection Props ํ˜•์‹ ์ˆ˜์ • #19 * ๐Ÿ’„ UI : Search Bar ๊ณต์šฉ ์‚ฌ์šฉ์œผ๋กœ ์ธํ•œ CSS ์ˆ˜์ • #19 * ๐Ÿ’„ UI : ๊ณต์šฉ BigCard ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI : SearchPage ๊ตฌํ˜„ #19 * ๐Ÿ’„ UI : SearchPage Recommended Title ์ปดํฌ๋„ŒํŠธ #19 * ๐Ÿ’„ UI : SearchPage TipSection ๊ตฌํ˜„ #19 * ๐Ÿ’„ UI : dummyImage MainPage์— ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI: LoginPage Input.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ ๋ฐ Style ์ˆ˜์ • #10 * โ™ป๏ธ refactor: LoginPage Button.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * ๐Ÿ’„ UI : Button ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #10 * ๐Ÿ’„ UI : Input ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage InterestTag.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #16 * โ™ป๏ธ refactor: MyPage Section.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #16 * ๐Ÿ’„ UI : InterestTag ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #16 * ๐Ÿ”ฅ remove: isAuth ์‚ญ์ œ #12 * โœจ feat: add font #22 * โœจ feat: add themeProvider #22 * โœจ feat: add globalStyle #22 * โœจ feat: add typography #22 * โ™ป๏ธย refactor: kakao_login ์ด๋ฏธ์ง€ ํŒŒ์ผ ์œ„์น˜ ๋ณ€๊ฒฝ #10 * โ™ป๏ธย refactor: <> ์‚ญ์ œ #10 * โœ๏ธย typo: ํด๋” ์ด๋ฆ„ ๋ณ€๊ฒฝ (MyPage_components -> components) #16 * โœ๏ธย typo: ์˜คํƒ€ ์ˆ˜์ • (ProfileCard2 -> ProfileCard) #16 * โ™ป๏ธ refactor: <> ์‚ญ์ œ #16 * โ™ป๏ธ refactor: import ๊ฒฝ๋กœ๋ฅผ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋กœ ๋ณ€๊ฒฝ #16 * โ™ป๏ธ refactor : keypress -> keydown ์œผ๋กœ ์ˆ˜์ • #19 * โ™ป๏ธ refactor : text1, text2 ์ˆซ์ž ์‚ฌ์šฉ front, backText ๋กœ ์ˆ˜์ • #19 * ๐Ÿ”ง config: package-lock ํŒŒ์ผ ์‚ญ์ œ * ๐Ÿ’„ UI: modify logo image file #25 * โœจ feat: ์ถ”๊ฐ€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜ #22 * โœจ feat: ์ถ”๊ฐ€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ํƒ€์ดํฌ ๋ฐ˜์˜ #22 * ๐Ÿ’„ UI: Title ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: LoginPage ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ“ฆ package: add vite-plugin-svgr #25 * ๐Ÿ”ง config: svg ์‚ฌ์šฉ ์œ„ํ•œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ์„ค์ • #25 * ๐Ÿ’„ UI: ์•Œ๋ฆผ ์•„์ดํ†ค ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: update Navigation Bar #25 * โœ๏ธ Typo: todo ํ…์ŠคํŠธ ์ค‘๋ณต ์‚ญ์ œ #25 * ๐Ÿ’„ UI: Input ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: Button ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: LoginPage ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„UI: logo ์•„์ด์ฝ˜ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: ํ‘ธํ„ฐ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜ #25 * โœจ feat: SignupPage ๊ตฌ์กฐ #21 * โœจ feat: ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ๊ณ ์ • #25 * โœจ feat: ํ”„๋กœํ•„ ์•„๋ฐ”ํƒ€ ์ƒ์„ฑ #21 * โœจ feat: ํ”„๋กœํ•„ ์ถ”๊ฐ€ ๋ฒ„ํŠผ #21 * ๐Ÿ”ง config: design system ์ถ”๊ฐ€ #24 * ๐Ÿ’„ UI: Tag ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #24 * ๐Ÿ’„ UI: Card ์ปดํฌ๋„ŒํŠธ ๋””์ž์ธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Banner UI ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Search UI ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Quiz ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: TipSection ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Category ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: MainPage ์ˆ˜์ • #24 * โœจ feat: ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€ #21 * ๐ŸŽจ style: alarm ์•„์ด์ฝ˜ ์ˆ˜์ • #25 * ๐Ÿ’„ UI: close icon ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: SearchSection margin ์ˆ˜์ • #24 * ๐Ÿ’„ UI: BigCard ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: SearchPage Tip ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์ˆ˜์ • #24 * โœจ feat: add alarm modal #25 * ๐Ÿ’„ UI: Banner UI ์ˆ˜์ • #24 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #25 * ๐Ÿ’„ UI: SavedTipSection Card Props ์ˆ˜์ • #24 * โ™ป๏ธ refactor: pํƒœ๊ทธ ์˜ค๋ฅ˜ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Design System ์ ์šฉ #24 * โ™ป๏ธ refactor: Console์˜ค๋ฅ˜ props attr DOM ๋žœ๋”๋ง ํ•ด๊ฒฐ #24 * ๐Ÿ’„ UI: errorMessage ์Šคํƒ€์ผ ์ถ”๊ฐ€ (๋นจ๊ฐ„ ํ…Œ๋‘๋ฆฌ) #34 * ๐Ÿ”ง config: ์—๋Ÿฌํ•ธ๋“ค๋ง์„ ์œ„ํ•œ useInput ์ปค์Šคํ…€ํ›… ์ถ”๊ฐ€ #34 * โœจ feat: ์ด๋ฉ”์ผ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ #34 * ๐Ÿ”ง config: ์ด๋ฉ”์ผ ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•œ validation ์ƒ์„ฑ #34 * ๐Ÿ“ฆ package: axios ์ถ”๊ฐ€ #34 * ๐Ÿ”ง config: errorHandler ์‚ญ์ œ์ œ #34 * โ™ป๏ธ refactor: ButtonBox ์‚ญ์ œ ํ›„ InputForm์— ํ•ฉ์น˜๊ธฐ๊ธฐ #34 * โœจ feat: ์ž๋™๋กœ๊ทธ์ธ ํด๋ฆญ ์‹œ ์ฒดํฌ๋ฐ•์Šค ํ™œ์„ฑํ™” #34 * Feat/#33 UI community page UI & CreateAndPostPage UI (#37) * ๐Ÿ’„ UI: recent/ likes / bookmarks ๊ธฐ๋Šฅ ์ˆ˜์ • #33 * ๐Ÿ’„ UI: Community Page Banner Component #33 * ๐Ÿ’„ UI: Community Page 1 ๊ตฌํ˜„ #33 * ๐Ÿ”ง config: --host ์ถ”๊ฐ€ #33 * ๐Ÿ’„ UI: plus ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #33 * ๐Ÿ’„ UI: Tag ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #33 * ๐Ÿ’„ UI: ์ด๋ฏธ์ง€ ์—…๋กœ๋” ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: Title ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: CreatePostPage ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: Categories ์ปดํฌ๋„ŒํŠธ ์žฌ์ˆ˜์ • #33 * ๐Ÿ’„ UI: SearchModal ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: SearchSection ์žฌ์ˆ˜์ • #33 * ๐Ÿ’„ UI: SearchModalBar ๊ตฌํ˜„ #33 * ๐Ÿ› fix : error ํ•ด๊ฒฐ๊ฒฐ * ๐Ÿ’„ UI: ํƒ€์ดํ‹€ ๋””์ž์ธ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ๋งˆ์ดํŽ˜์ด์ง€ UI ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: Tag ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: Section ์ปดํฌ๋„ŒํŠธ UI ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ˆ˜์ • ์กฐ๊ฑด๋ถ€ ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์กฐ๊ฑด ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ํ”„๋กœํ•„์นด๋“œ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์กฐ๊ฑด ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํŽธ์ง‘ํ•˜๊ธฐ ๋ฒ„ํŠผ ์ถ”๊ฐ€ #29 * โœจ feat: profileEdit ๋ฒ„ํŠผ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ ๋ฐ onClick ์†์„ฑ ์ถ”๊ฐ€ #29 * โœจ feat: add ProfileEditModal router #29 * ๐Ÿ’„ UI: ๋“œ๋กญ๋‹ค์šด ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #29 * ๐Ÿ“ฆ package: ์ง€์—ญ ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ #29 * โœจ feat: profileEdit ๋ชจ๋‹ฌ ์ƒ์„ฑ #29 * โœจ feat: profileEdit ๋ชจ๋‹ฌ ์—ฐ๊ฒฐ #29 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #29 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #29 * โœ๏ธ Typo: ํ•„์š”์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ #29 * โœจ feat: interestEdit ๋ฒ„ํŠผ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ๋ฒ„ํŠผ padding ์ˆ˜์ • #29 * โœจ feat: interestEdit ๋ชจ๋‹ฌ ์ƒ์„ฑ #29 * โœจ feat: interestEdit ๋ชจ๋‹ฌ ์—ฐ๊ฒฐ #29 * โœจ feat: ๋ชจ๋‹ฌ ์ƒ๋‹จ์— X ๋‹ซ๊ธฐ ๋ฒ„ํŠผ ์ƒ์„ฑ #29 * โœจ feat: add SignUpPage ์ „์ฒด ์ˆ˜์ • #21 * โœจ feat: add SignupState ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ #21 * โœจ feat: button์— pageUp, pageDown, signUp ๋ณ€์ˆ˜ ์ƒ์„ฑ #21 * โœจ feat: Section1 ์•ฝ๊ด€ ๋™์˜ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: button์— disabled ์†์„ฑ ์ƒ์„ฑ #21 * โœจ feat: ํ•„์ˆ˜ ์•ฝ๊ด€ ๋™์˜์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: Button์— disabled ์Šคํƒ€์ผ ์ถ”๊ฐ€ #21 * โœจ feat: + ๋ˆŒ๋ €์„ ๋•Œ ์•ฝ๊ด€ ์ƒ์„ธ ๋‚ด์šฉ ๋„์šฐ๊ธฐ ์ถ”๊ฐ€ #21 * โœจ feat: button์— emailCheck ๋ณ€์ˆ˜ ์ƒ์„ฑ #21 * โœจ feat: Section2 ์ด๋ฉ”์ผ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: Section3 ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * ๐Ÿ’„ UI: ์ œ๋ชฉ ์ƒ‰์ƒ primary[700]์œผ๋กœ ๋ณ€๊ฒฝ #21 * โœจ feat: Section4 ๊ฐœ์ธ์ •๋ณด ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: Section4 ๋‹ค์Œ ๋ฒ„ํŠผ ์ถ”๊ฐ€ ์ˆ˜์ • #21 * โœจ feat: Section5 ๊ด€์‹ฌ์‚ฌ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: ํšŒ์›๊ฐ€์ž… ์™„๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ฉ”์ธํ™”๋ฉด์œผ๋กœ #21 * โœจ feat: Section4 ํ”„๋กœํ•„ ์นด๋ฉ”๋ผ ์ปค์„œ ํฌ์ธํ„ฐ #21 * โœจ feat: ๋‹‰๋„ค์ž„ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: ์ด๋ฉ”์ผ ๋ฐ ์ธ์ฆ๋ฒˆํ˜ธ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœ๏ธ Typo: ์„น์…˜ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ๋ณ€๊ฒฝ #21 * ๐Ÿ’„ UI: ๋ฒ„ํŠผ ๊ธ€์ž์ˆ˜์— ๋งž๊ฒŒ ์„ ํƒ์ƒ์ž ํฌ๊ธฐ ์ˆ˜์ • ๋ฐ font style ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ์ž๋™๋กœ๊ทธ์ธ ์ฒดํฌ๋ฐ•์Šค ์ƒ‰์ƒ ๋ณ€๊ฒฝ #34 * Feat/#38 pagination ๊ตฌํ˜„ & Skeleton UI TipSection (#40) * ๐Ÿ”ง config: .env gitignore ์„ค์ • #38 * ๐Ÿ”ง config: axios, react-query ์„ค์น˜ #38 * ๐Ÿ”ง config: ReactQueryDevtools, queryClient ์„ค์ • #38 * โœจ feat: axios ๊ธฐ๋ณธ hook #38 * ๐Ÿ’„ UI: dummyData ์ƒ์„ฑ #38 * โœจ feat: useGetTips hook ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection Component ์ˆ˜์ • #38 * ๐Ÿ’„ UI: TipsSection Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: Props ๋กœ ์ธํ•œ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * โœจ feat: Pagination ๊ธฐ๋Šฅ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection ํƒ€์ž… ์ถ”๊ฐ€ #38 * โœจ feat: SkeletonCard UI ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: SkeletonBigCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #38 * # UI: RecommendTips ๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: CommunityPage TipSection ์ปดํฌ๋„ŒํŠธ Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: BigCard pํƒœ๊ทธ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * Feat/#46 feat quiz banner (#47) * ๐Ÿ”ง config: .env gitignore ์„ค์ • #38 * ๐Ÿ”ง config: axios, react-query ์„ค์น˜ #38 * ๐Ÿ”ง config: ReactQueryDevtools, queryClient ์„ค์ • #38 * โœจ feat: axios ๊ธฐ๋ณธ hook #38 * ๐Ÿ’„ UI: dummyData ์ƒ์„ฑ #38 * โœจ feat: useGetTips hook ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection Component ์ˆ˜์ • #38 * ๐Ÿ’„ UI: TipsSection Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: Props ๋กœ ์ธํ•œ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * โœจ feat: Pagination ๊ธฐ๋Šฅ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection ํƒ€์ž… ์ถ”๊ฐ€ #38 * โœจ feat: SkeletonCard UI ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: SkeletonBigCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #38 * # UI: RecommendTips ๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: CommunityPage TipSection ์ปดํฌ๋„ŒํŠธ Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: BigCard pํƒœ๊ทธ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * ๐Ÿ”ง config: ์ƒํƒœ๊ด€๋ฆฌ zustand ์„ค์น˜ #41 * ๐Ÿ’„ UI: dummyCategories ํด๋” ์ด๋™ #41 * ๐Ÿ’„ UI: SearchBar Icon ์ˆ˜์ • #41 * ๐Ÿ’„ UI: DummyCat ์ถ”๊ฐ€ #41 * โœจ feat: CreateAndPost Post Api ์—ฐ๋™ #41 * โœจ feat: Complete Modal ๊ตฌํ˜„ #41 * ๐Ÿ”ง config: framer-motion ์„ค์น˜ #46 * ๐Ÿ’„ UI: Icon, character ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #46 * โœจ feat: quiz Store ๊ตฌํ˜„ #46 * ๐Ÿ’„ UI: QuizBox ํ–‰๋™ ๊ตฌํ˜„ #46 * ๐Ÿ”ง config: develop ๋ฌธ์ œ ํ•ด๊ฒฐ #46 * ๐Ÿšจ conflict ํ•ด๊ฒฐ #46 * ๐Ÿ’„ UI: Vecel ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #46 * โœจ feat: kakaocallbackํŽ˜์ด์ง€ ๊ตฌํ˜„ ๋ฐ ๋ผ์šฐํ„ฐ #49 * โœ๏ธ Typo: eslint ๋ฌด์‹œ ๋ฌธ๊ตฌ ์‚ญ์ œ #49 * โœจ feat: ํšŒ์›๊ฐ€์ž… ํด๋ฆญ ์‹œ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ #49 * โœจ feat: ํšŒ์› ์ •๋ณด ์ฐพ๊ธฐ ํŽ˜์ด์ง€ ์ƒ์„ฑ #49 * โœจ feat: ํšŒ์› ์ •๋ณด ์ฐพ๊ธฐ ํŽ˜์ด์ง€ ์—ฐ๊ฒฐ #49 * Feat/#43 UI save tip page (#50) * โœจ feat: SaveTipPage ๊ตฌํ˜„ #43 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ #43 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ณ€๊ฒฝ #43 * โœจ feat: SkeletonImage width 240px๋กœ ๋ณ€๊ฒฝ#43 * โœจ feat: ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„ #43 * โœจ feat: Card ์ปดํฌ๋„ŒํŠธ onClick ์†์„ฑ ์ถ”๊ฐ€ #43 * โœจ feat: ์นด๋“œ ์ปดํฌ๋„ŒํŠธ ํด๋ฆญ ์‹œ ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ #43 * โœจ feat: ๋งˆ์ดํŽ˜์ด์ง€ ์ตœ๊ทผ ๋ณธ ๊ฟ€ํŒ ์ƒ์„ธํŽ˜์ด์ง€ ์—ฐ๊ฒฐ #43 * โœจ feat: onClick ์†์„ฑ์— ?์„ ํƒ ์ถ”๊ฐ€ #43 --------- Co-authored-by: rael * Feat/#54 feat quiz modify and on click add (#56) * โœจ feat: BigCard OnClick ํ•จ์ˆ˜ ๊ตฌํ˜„ #54 * โ™ป๏ธ refactor: Exit Animation ๊ตฌํ˜„ ์™„๋ฃŒ #54 * โœจ feat: RecommedTip OnClick ์—ฐ๊ฒฐ #54 * โœจ feat: Post ์˜ค๋ฅ˜ ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ - ์„œ๋ฒ„ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ํ›„ ๋‹ค์‹œ ์‹œ๋„ ์˜ˆ์ • #54 * Feat/#36 UI magazine (#51) * ๐Ÿ”ง config: framer-motion ๋ฒ„์ „ ์ˆ˜์ • #36 * โœจ feat: add mind-map component #36 * โœจ feat: add card-grid component #36 * โ™ป๏ธ refactor: card์—์„œ cardInfo ๋ถ„๋ฆฌ #36 * ๐Ÿ’„ UI: add MagazinePage #36 * ๐Ÿ’„ UI: add MagazineDetailPage #36 * Feat/#53 api folder stucture (#55) * ๐Ÿ”ง config: framer-motion ๋ฒ„์ „ ์ˆ˜์ • #36 * โœจ feat: add mind-map component #36 * โœจ feat: add card-grid component #36 * โ™ป๏ธ refactor: card์—์„œ cardInfo ๋ถ„๋ฆฌ #36 * ๐Ÿ’„ UI: add MagazinePage #36 * ๐Ÿ’„ UI: add MagazineDetailPage #36 * ๐Ÿ”ฅ remove: index file from api folder #53 * ๐Ÿ”ฅ remove: queries folder from hooks #53 * โœจ feat: tip ๊ด€๋ จ api ํ˜ธ์ถœ ์ถ”๊ฐ€ #53 * โœจ feat: tip ๊ด€๋ จ query ์ถ”๊ฐ€ #53 * โ™ป๏ธ refactor: api ํ˜ธ์ถœ ๋ฐฉ์‹ ์ˆ˜์ • #53 * โœจ feat: policy api ์ถ”๊ฐ€ #53 * โœจ feat: policy query ์ถ”๊ฐ€ #53 * โœจ feat: title ์†์„ฑ ์ˆ˜์ • #53 * ๐Ÿ’ฌ comment: ์ฃผ์„ ์ˆ˜์ • #53 * Feat/#52 ๋žœ๋”ฉํŽ˜์ด์ง€, ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ชจ๋‹ฌ์ฐฝ UI (#57) * ๐Ÿ› bug: DOM ๊ฒฝ๊ณ ์ฐฝ ํ•ด๊ฒฐ #52 * ๐Ÿ’„ UI: ๋กœ๊ณ  ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ #52 * ๐Ÿ’„ UI: ์บ๋ฆญํ„ฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #52 * ๐Ÿ› bug: DOM ๊ฒฝ๊ณ ์ฐฝ ํ•ด๊ฒฐ #52 * ๐Ÿ’„ UI: ํ”„๋กœํ•„ ๋ชจ๋‹ฌ ๊ด€๋ จ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #52 * โœจ feat: ํ”„๋กœํ•„ ๋ชจ๋‹ฌ ๊ตฌํ˜„ #52 * โœจ feat: ๋žœ๋”ฉํŽ˜์ด์ง€ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธํ™” #52 * ๐Ÿ’„ UI: ๋žœ๋”ฉํŽ˜์ด์ง€ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜ #52 * ๐Ÿ’„ UI: dot ๋””์ž์ธ ์ˆ˜์ • #52 * Feat/#44 UI save tip detail page (#58) * โœจ feat: SaveTipDetail ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ๊ตฌํ˜„ #44 * โ™ป๏ธ refactor: PostDetail ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #44 * โ™ป๏ธ refactor: CommentView ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #44 * โœ๏ธ Typo: props ์ค‘๋ณต ์‚ญ์ œ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ์ž…๋ ฅ์ฐฝ ๊ตฌํ˜„ #44 * โœจ feat: ๋Œ“๊ธ€ ์ž…๋ ฅ ๊ธฐ๋Šฅ ๋ฐ ๋”๋ณด๊ธฐ ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€๋ชฉ๋ก gap ์ˆ˜์ • #44 * ๐Ÿ”ง config: .gitignore์— .env ์ถ”๊ฐ€ #44 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ฐ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹ ์ˆ˜์ • #44 * โœ๏ธ Typo: ๋Œ“๊ธ€์— ... ์‚ญ์ œ #44 * โœ๏ธ Typo: ๋‹จ์–ด ์ˆ˜์ • #44 * โœ๏ธ Typo: ์˜คํƒ€ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ๊ธฐ์กด ๋Œ“๊ธ€ ์‚ญ์ œ #44 * ๐Ÿ’„ UI: ์ข‹์•„์š”, ์ €์žฅํ•˜๊ธฐ, ๊ณต์œ ํ•˜๊ธฐ ๋ฒ„ํŠผ ์ƒ์„ฑ ๋ฐ useState ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: PAGE_SIZE 5๊ฐœ๋กœ ์ˆ˜์ • #44 * ๐Ÿ’„ UI: SkeletonComment ๋Œ“๊ธ€ UI ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ๋ฌดํ•œ์Šคํฌ๋กค ๊ตฌํ˜„ #44 * ๐Ÿ“ฆ package: ๋Œ“๊ธ€ ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ˆ˜์ • #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ๋ฌดํ•œ์Šคํฌ๋กค 3๊ฐœ์”ฉ ๋กœ๋”ฉ #44 --------- Co-authored-by: rael * Fix/#59 fix search page modify (#61) * ๐Ÿ”จ fix: react Hook Rendering ์ˆœ์„œ ๋ณ€๊ฒฝ #59 * ๐Ÿ”จ fix: title Default ๊ฐ’ ์ œ๊ฑฐ ๋ฐ undefined ๋ฐฉ์ง€ #59 * Feat/#62 feat token zustand (#63) * โœจ feat: zustand ์ „์—ญ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ†ตํ•œ refresh Token ๊ตฌํ˜„ #62 * โœจ feat: hashtags 2์ค‘ ๋ฐฐ์—ด๋กœ post #62 * ๐Ÿ’„ UI: TipSection Animation ์ถ”๊ฐ€ #62 * ๐Ÿ’„ UI: height ๋ณ€๋™ #62 * โœจ feat: RoutePaths ์‚ฌ์šฉ #62 * โœจ feat: handleEmailLogin #49 * โœจ feat: ํ”„๋กœํ•„ ๋“œ๋ž๋‹ค์šด ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋กœ๊ทธ์•„์›ƒ ์ถ”๊ฐ€ #49 * โœจ feat: ๋กœ๊ทธ์ธ ์‹œ ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ”„๋กœํ•„๋กœ ๋ณ€๊ฒฝ #49 * โœจ feat: ์ „์—ญ์ƒํƒœ๊ด€๋ฆฌ๋กœ ๋กœ๊ทธ์ธ ์ƒํƒœ ๊ด€๋ฆฌ #49 * โœจ feat: ์ด๋ฉ”์ผ ๋กœ๊ทธ์ธ API ์—ฐ๊ฒฐ #49 * โœจ feat: User ์ •๋ณด ์—ฐ๊ฒฐ #49 * ๐Ÿ› bug: ์ค‘๋ณต ํŒŒ์ผ ์‚ญ์ œ์ œ * Feat/#64 feat main page modify (#68) * ๐Ÿ’„ UI: NavigationBar z-index ์ˆ˜์ • #64 * ๐Ÿ’ฌ comment: refresh ํ† ํฐ ์„ฑ๊ณต ํ™•์ธํ›„ ํ† ํฐ ์ฝ˜์†” ์ฃผ์„ํ™” #64 * ๐Ÿ’„ UI: DummyData id ์ถ”๊ฐ€ #64 * โœจ feat: Banner Animation ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #64 * โœจ feat: NavigationBar ๊ฐœ๋ฐœ์ž๋ชจ๋“œ์—์„œ ๋ฆฌ๋žœ๋”๋ง ๋ฌธ์ œ ์ž„์‹œ ํ•ด๊ฒฐ #64 * โœจ feat: Quiz Hook ๊ตฌํ˜„ #64 * โœจ feat: Search Hook ๊ตฌํ˜„ #64 * โœจ feat: TipSection Api ์—ฐ๋™ ๋ฐ ์ปดํฌ๋„ŒํŠธ ์žฌํ™œ์šฉ ํšจ์œจ ํ–ฅ์ƒ #64 * โ™ป๏ธ refactor: hashtags ์ด์ค‘ ๋ฐฐ์—ด์—์„œ ๊ทธ๋ƒฅ ๋ฐฐ์—ด๋กœ post #64 * โœจ feat: SearchPage Search Hook ์‚ฌ์šฉ ๋ฐ TipItem ํƒ€์ž… transform ์„ค์ • #64 * ๐Ÿ’„ UI: Categories UI ์  ์š”์†Œ ์žฌ๊ตฌ์„ฑ #64 * โœจ feat: Quiz API ์—ฐ๊ฒฐ ๋ฐ ํ™”๋ฉด ๊ตฌ์„ฑ #64 * โœจ feat: quizAnswer Hook ๊ตฌํ˜„ #64 * โœจ feat: QuizAnswer Hook ๊ตฌํ˜„ 2 #64 * โœจ feat: QuizAnswer Api ์—ฐ๊ฒฐ #64 * โ™ป๏ธ refactor: ํฐ ํ™”๋ฉด์—์„œ ๋ฐฐ๋„ˆ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ€๋กœ ์Šคํฌ๋กค ๋ฐœ์ƒ ๋ฌธ์ œ ํ•ด๊ฒฐ #64 * ๐Ÿ’ฌ comment: Quiz Skeleton UI ๊ตฌํ˜„์ „ ์ฃผ์„์ฒ˜๋ฆฌ #64 * โ™ป๏ธ refactor: axios-instance ์ž์ฒด์— ๊ถŒํ•œ ์ˆ˜์—ฌ #64 * ๐Ÿ”จ fix: ์ •๋‹ต์ผ ๋•Œ๋งŒ server๋กœ post #64 * โ™ป๏ธ refactor: quizAPI ํŒŒ์ผ ์ด๋ฆ„ ์ •๋ฆฌ ๋ฐ api ํ†ตํ•ฉ #64 * โ™ป๏ธ refactor: ์ˆ˜์ •๋œ hook ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ #64 * Feat/#73 feat create page modify (#74) * โœจ feat: ๊ธ€ ์ƒ์„ฑ์‹œ userID ์ถ”๊ฐ€ #73 * โœจ feat: TipCreate Api ๋ถ„๋ฆฌ #73 * โœจ feat: SearchModal Close์‹œ ์ž…๋ ฅ์ฐฝ ์ดˆ๊ธฐํ™” #73 * Feat/#75 UI challenge page UI (#77) * โœจ feat: ๊ธ€ ์ƒ์„ฑ์‹œ userID ์ถ”๊ฐ€ #73 * โœจ feat: TipCreate Api ๋ถ„๋ฆฌ #73 * โœจ feat: SearchModal Close์‹œ ์ž…๋ ฅ์ฐฝ ์ดˆ๊ธฐํ™” #73 * โœจ feat: FetchUser ํ›„ user.nickname ๋ถˆ๋Ÿฌ์˜ค๊ธฐ #75 * ๐Ÿ’„ UI: ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #75 * ๐Ÿ’„ UI: Card border-radius ์ˆ˜์ • #75 * โœจ feat: RoutePath์— Challenge ์ถ”๊ฐ€ #75 * โœจ feat: NumberCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: Challenge Banner ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: ChallengeHeader ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: Challenge TipSection ๊ตฌํ˜„ ๋ฐ InfiniteScroll / Skeleton UI ์ ์šฉ #75 * ๐Ÿ’„ UI: ChallengePage UI #75 * Feat/#79 feat image upload & ErrorPage & SearchTag (#80) * โœจ feat: Image Post ์ถ”๊ฐ€ #79 * โœจ feat: ErrorPage ๊ตฌํ˜„ ๋ฐ ์—ฐ๊ฒฐ #79 * โ™ป๏ธ refactor: SearchPage ์—๋Ÿฌ ๋ฐœ์ƒ ์ฝ”๋“œ ์ž„์‹œ ์กฐ์น˜ ์ถ”ํ›„ ์ˆ˜์ • ์˜ˆ์ • #79 * โœจ feat: Search Tag ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #79 * โœจ feat: Image Upload์‹œ ์—ฌ๋Ÿฌ ๋ฒˆ ์—…๋กœ๋“œ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ #79 * โ™ป๏ธ refactor: API interface Type ์„ค์ • #79 * Feat/#60 UI chatbot (#81) * โœจ feat: ์ฑ—๋ด‡ ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ „์†ก ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ๊ฒ€์ƒ‰๋ฐ” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ํŽ˜์ด์ง€ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์˜ค๋ฅธ์ชฝ ํ™”์‚ดํ‘œ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์‚ฌ์ด๋“œ๋ฐ” ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€ #60 * ๐Ÿ’ฌ comment: ์ฑ—๋ด‡ ์ฃผ์„ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: add chatbot icon #60 * โœจ feat: ์ฑ„ํŒ…๋ฐฉ ์ €์žฅ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #60 * โœจ feat: ์—”ํ„ฐ ํด๋ฆญ์‹œ ์ „์†ก ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #60 * โœจ feat: ๋ฒ„ํŠผ ์—ฐ๊ฒฐ #60 * โœจ feat: ์ฑ„ํŒ… api ์—ฐ๊ฒฐ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜ #60 * โœจ feat: ๋ฒ„ํŠผ๋ณ„ ์งˆ๋ฌธ ํ…์ŠคํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ› bug: ์ฒซํด๋ฆญ ์ฑ„ํŒ… ์•ˆ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #60 * ๐Ÿ”จ fix: ๋ผ์šฐํŠธ ๋จธ์ง€ ํ•ด๊ฒฐ #60 * Feat/#85 feat main page filter & chatbot Icon (#87) * ๐Ÿ’„ UI: ChatBot Icon ์ถ”๊ฐ€ #85 * โœจ feat: ๋‚ ์งœ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #85 * ๐Ÿ”ฅ remove: RecommedTipSection ์‚ญ์ œ #85 * โ™ป๏ธ refactor: SearchApi Tag๋กœ๋งŒ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ query ์˜ต์…”๋„ ์ถ”๊ฐ€ #85 * โœจ feat: user HashTag Get, Post #85 * โ™ป๏ธ refactor: TipSection ์žฌํ™œ์šฉ์„ฑ ๊ทน๋Œ€ํ™” / useTipList, useSearchList ์กฐ๊ฑด๋ฌธ์„ ํ†ตํ•ด ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ / Card ์™€ BigCard ์กฐ๊ฑด๋ฌธ์œผ๋กœ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ #85 * ๐Ÿ’„ UI: ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ title ๋ฌธ๊ตฌ ์ˆ˜์ • ๋ฐ ๋ฐ์ดํ„ฐ ์ˆ˜์ • #85 * โ™ป๏ธ refactor: useSearchList Sorted ์˜ต์…˜ ์ถ”๊ฐ€ #85 * โ™ป๏ธ refactor: defaultSort Props ์ถ”๊ฐ€ #85 * ๐Ÿ’„ UI: ์นดํ…Œ๊ณ ๋ฆฌ visible default ์ˆ˜์ • #85 * โœ๏ธ typo: bookmarks -> saves #85 * ๐Ÿ”ฅ remove: console.log ์ œ๊ฑฐ #85 * โ™ป๏ธ refactor: query ์ถ”๊ฐ€ ๋ฐ isMoreLimit ์กฐ๊ฑด ์ถ”๊ฐ€ #85 * ๐Ÿ”ฅ remove: console ์ œ๊ฑฐ #85 * Feat/#84 UI my challenge (#88) * โœจ feat: MyChallenge Path ์ถ”๊ฐ€ #84 * ๐Ÿ”จ fix: navigate ์ฃผ์†Œ ์ˆ˜์ • #84 * ๐Ÿ’„ UI: MyChallenge UI ๊ตฌํ˜„ #84 * ๐Ÿ’„ UI: Challenge Tip Skeleton ์ถ”๊ฐ€ #84 * ๐Ÿ’„ UI: cursor: pointer ์ถ”๊ฐ€ ์™„๋ฃŒ #84 * Feat/#90 UI challenge detail page (#91) * ๐Ÿ”ง config: ์ฑŒ๋ฆฐ์ € ์ƒ์„ธ ํŽ˜์ด์ง€ ๋ผ์šฐํ„ฐ ์—ฐ๊ฒฐ #90 * โœจ feat: onCardClick ์†์„ฑ ์ถ”๊ฐ€ #90 * โœจ feat: onCardClick ํ•จ์ˆ˜ ์ถ”๊ฐ€ [#90] * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ #90 * โœจ feat: ChallengeDetailPage ์ถ”๊ฐ€ #90 * โœจ feat: ChallengeDetail ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #90 * โœจ feat: ChallengeComment ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #90 * โ™ป๏ธ refactor: FloatingToggleBtn ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #90 * ๐Ÿ’„ UI: ์ฑŒ๋ฆฐ์ง€ ์ƒ์„ธ ํŽ˜์ด์ง€ UI ๊ตฌํ˜„ #90 * ๐Ÿ’„ UI: ์ฑŒ๋ฆฐ์ง€ ์ƒ์„ธ ํŽ˜์ด์ง€ ์ฐธ๊ฐ€์ž ํ›„๊ธฐ UI ๊ตฌํ˜„ #90 * โœจ feat: handleCardClick ์ถ”๊ฐ€ [#90] * Feat/#76 feature page api (#92) * ๐Ÿ’„ UI: ๋งˆ์ดํŽ˜์ด์ง€ UI ์ˆ˜์ • #76 * โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ (์ด๋ฏธ์ง€ ์ˆ˜์ • api ํ•„์š”) #76 * โœจ feat: ์ตœ๊ทผ ๋ณธ ๊ฟ€ํŒ ๊ธฐ๋Šฅ (์ €์žฅ๋œ ๊ฟ€ํŒ ํŽ˜์ด์ง€๊นŒ์ง€๋งŒ ์ถ”๊ฐ€๋จ/๋ฉ”์ธ, ๋งค๊ฑฐ์ง„ ๋“ฑ๋“ฑ handleCardClick ์ถ”๊ฐ€์ˆ˜์ • ํ•ด์•ผํ•จ.) #76 * โœจ feat: ๋ฌดํ•œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ํ•ด๊ฒฐ #76 * ๐Ÿ“ฆ package: InfiniteQuery ์ถ”๊ฐ€ #76 * โœจ feat: getSavedTips api ์ถ”๊ฐ€ (์•„์ง ์—๋Ÿฌ ํ•ด๊ฒฐX) #76 * โœจ feat: useSaveTipList ์ฟผ๋ฆฌ ์ด์šฉํ•ด์„œ ๋ฌดํ•œ์Šคํฌ๋กค ์ถ”๊ฐ€ ์‹œ๋„ #76 * โœจ feat: api ์—ฐ๊ฒฐ ์ค‘ #76 * โœจ feat: tip ํ˜•์‹ ํ†ต์ผ #76 * โœจ feat: ์นด์นด์˜ค ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #76 * โœจ feat: getTipDetail api, useTipDetail ์ถ”๊ฐ€ #76 * โœจ feat: dummydata ์‚ญ์ œ ํ›„ api ์—ฐ๊ฒฐ ์‹œ๋„ #76 * โœจ feat: comment get, post, put, delete api ์ถ”๊ฐ€ #76 * โœจ feat: ์ข‹์•„์š”์™€ ๋ถ๋งˆํฌ ํ† ๊ธ€ api ์ถ”๊ฐ€ #76 * โœจ feat: ์ข‹์•„์š”์™€ ๋ถ๋งˆํฌ mutation ์ถ”๊ฐ€ #76 * ๐Ÿ’„ UI: ํ† ๊ธ€ ๋ฒ„ํŠผ๋“ค ์ปดํฌ๋„ŒํŠธํ™” #76 * โ™ป๏ธ refactor: ์ปดํฌ๋„ŒํŠธํ™” ๋ฐ˜์˜ #76 * ๐Ÿ’„ UI: ๊ฟ€ํŒ ์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #76 * โ™ป๏ธ refactor: ์ €์žฅ ์œ„์น˜ ๋ณ€๊ฒฝ #76 * โœจ feat: ์ €์žฅ ๊ฟ€ํŒ ๋ฐ˜ํ™˜๊ฐ’ ์ˆ˜์ • #76 * ๐Ÿ’„ UI: modify width #76 * ๐Ÿ’„ UI: remove text #76 * โœจ feat: ์ €์žฅํ•œ ๊ฟ€ํŒ api ์—ฐ๊ฒฐ #76 * โœจ feat: ์นด์นด์˜ค ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์˜ค๋ฅ˜ ์ˆ˜์ • [#76] * ๐Ÿ’„ UI: cursor pointer ์ถ”๊ฐ€ [#76] * โœจ feat: ์ด๋ฉ”์ผ ์ž…๋ ฅ ํผ api ์ˆ˜์ • #76 * โœจ feat: ์ข‹์•„์š” ๋ฐ ์ €์žฅ ์—ฌ๋ถ€ ์ €์žฅ #76 * ๐Ÿ’ฌ comment: ์ฃผ์„ ์‚ญ์ œ #76 * โ™ป๏ธ refactor: DTO ์ˆ˜์ •์‚ฌํ•ญํ•ญ ๋ฐ˜์˜ #76 * โœจ feat: ๋Œ“๊ธ€ api ์—ฐ๊ฒฐ #76 * โœจ feat: ๋Œ“๊ธ€ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #76 * ๐Ÿ› bug: ์นด์นด์˜ค ๊ณต์œ  #76 * โœจ feat: ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ ๋ฐ˜์˜ #76 * ๐Ÿ› bug: ํƒ€์ž… ์—๋Ÿฌ ํ•ด๊ฒฐ #76 * โ™ป๏ธ refactor: ๋Œ“๊ธ€ ์ธํ„ฐํŽ˜์ด์Šค ์ ์šฉ #76 * โœจ feat: ํšŒ์›๊ฐ€์ž… api ์—ฐ๊ฒฐ #76 * โœจ feat: userStore updateProfile ์ถ”๊ฐ€ #76 * โœจ feat: ์˜ค๋ฅ˜ ์ˆ˜์ • #76 * ๋ณต์ œ ๋ฌธ์„œ ์‚ญ์ œ * โœจ feat: ํšŒ์›๊ฐ€์ž… ์˜ค๋ฅ˜ ์ˆ˜์ •์ค‘ #76 --------- Co-authored-by: rael Co-authored-by: Head-ddy <80982532+Head-ddy@users.noreply.github.com> * Feat/#89 Navigation bar UI (#93) * ๐Ÿ’„ UI: ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ˜ธ๋ฒ„๋ง ์ถ”๊ฐ€ #89 * โœจ feat: ํŒŒ๋น„์ฝ˜ ์ถ”๊ฐ€ #89 * ๐Ÿ› bug: ์ถฉ๋Œ ์—๋Ÿฌ ํ•ด๊ฒฐ * Feat/#82 api magazine (#94) * ๐Ÿ’„ UI: ๋งค๊ฑฐ์ง„ ์บ๋ฆญํ„ฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #82 * โœจ feat: ์ธ๊ธฐ ํ•ด์‹œํ…Œ๊ทธ ์—ฐ๊ฒฐ #82 * โœจ feat: ๋งค๊ฑฐ์ง„ ์ƒ์„ธ ์ •๋ณด api ์—ฐ๊ฒฐ #82 * โœจ feat: ์ „์ฒด ์ด๋ฏธ์ง€๋ณด๊ธฐ ๋ชจ๋‹ฌ ์ถ”๊ฐ€ #82 * ๐Ÿ› bug: ์ •์ฑ… api ์ธํ„ฐํŽ˜์ด์Šค ์ˆ˜์ • #82 * ๐Ÿ› bug: ํƒ€์ž… ์—๋Ÿฌ๋Ÿฌ * Fix/#96 fix landing page access (#98) * โœจ feat: AuthWrapper ํ†ตํ•ด ๊ถŒํ•œ ์—†์ด ๋‹ค๋ฅธ ํŽ˜์ด์ง€ ์ ‘๊ทผ ์ œํ•œ #96 * โ™ป๏ธ refactor: ์‹ค์ œ accessToken ์œผ๋กœ ์ ‘๊ทผ #96 * โ™ป๏ธ refactor: refreshToken Default ๊ฐ’ null ์„ค์ • #96 * Feat/#66 fix signup modify (#99) * ๐Ÿ”ง config: gitignore ์ˆ˜์ • #66 * โœจ feat: ์ „์ฒด ์ด์šฉ์•ฝ๊ด€ ์ฒดํฌ๋ฐ•์Šค ์˜ค๋ฅ˜ ์ˆ˜์ • #66 * โœ๏ธ Typo: ํ•„์š”์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ #66 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ๋‹‰๋„ค์ž„ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ๋‹‰๋„ค์ž„ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ #66 * ๐Ÿ’„ UI: ํšŒ์›๊ฐ€์ž… ๋‹จ๊ณ„ UI ์ˆ˜์ • #66 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต! #66 * โœจ feat: ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ ๋ฐ ๋ฒ„ํŠผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ #66 * โœจ feat: api ์ˆ˜์ • #66 * โœจ feat: ํšŒ์›๊ฐ€์ž… ํ›„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ #66 * โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ #66 * โœจ feat: ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ ์ˆ˜์ • #66 * ๐Ÿ’„ UI: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต alert ์ถ”๊ฐ€ #66 * Fix/#97/saved tips (#100) * โœจ feat: ์ƒ๋‹จ ์Šคํฌ๋กค ๊ธฐ๋Šฅ #97 * โœจ feat: ๋กœ๊ณ  ์ด๋ฏธ์ง€์—๋„ ์ƒ๋‹จ ์Šคํฌ๋กค ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #97 * ๐Ÿ’„ UI: ํฌ์ธํ„ฐ ์ถ”๊ฐ€ #97 * โœจ feat: ์ข‹์•„์š” & ์ €์žฅ ์ˆ˜ ์ถ”๊ฐ€ #97 * โœจ feat: ์‚ฌ์ง„ ๊ฐœ์ˆ˜์— ๋”ฐ๋ฅธ ๊ทธ๋ฆฌ๋“œ ์ถ”๊ฐ€ #97 * โœจ feat: ์‚ฌ์ง„ 5๊ฐœ ์ž„์‹œ ๊ทธ๋ฆฌ๋“œ #97 * โœจ feat: profile image ์ถ”๊ฐ€ #97 --------- Co-authored-by: S-Gihun <89789115+S-Gihun@users.noreply.github.com> Co-authored-by: rael Co-authored-by: Head-ddy <80982532+Head-ddy@users.noreply.github.com> Co-authored-by: Rael --- umc-master/src/apis/authApi.ts | 50 ++++------- umc-master/src/apis/axios-instance.ts | 10 +-- .../src/components/Auth/AuthWrapper.tsx | 30 +++++++ umc-master/src/components/Modal/profile.tsx | 10 +-- .../NavigationBar/NavigationBar.tsx | 28 ++++-- umc-master/src/pages/auth/SignUpPage.tsx | 8 +- .../auth/Signup_components/AgreementForm.tsx | 25 +++--- .../auth/Signup_components/EmailForm.tsx | 43 ++++++++-- .../auth/Signup_components/PasswordForm.tsx | 43 ++++++++-- .../auth/Signup_components/PrivacyForm.tsx | 68 ++++++++++++--- .../auth/Signup_components/SignupState.tsx | 7 +- .../src/pages/community/components/Banner.tsx | 1 + umc-master/src/pages/saveTip/SaveTipPage.tsx | 4 +- .../pages/saveTip/components/PostDetail.tsx | 86 +++++++++++++++++-- umc-master/src/router/routes.tsx | 54 +++++++----- umc-master/src/store/tokenStore.ts | 2 +- 16 files changed, 338 insertions(+), 131 deletions(-) create mode 100644 umc-master/src/components/Auth/AuthWrapper.tsx diff --git a/umc-master/src/apis/authApi.ts b/umc-master/src/apis/authApi.ts index 55d9c5c..0052887 100644 --- a/umc-master/src/apis/authApi.ts +++ b/umc-master/src/apis/authApi.ts @@ -1,38 +1,18 @@ -// import axiosInstance from '@apis/axios-instance'; +import axiosInstance from '@apis/axios-instance'; -// interface UserSignup { -// email: string; -// password: string; -// nickname: string; -// hashtags: string[]; -// } +interface UserSignup { + email: string; + password: string; + nickname: string; + hashtags: string[]; +} -// export const postSignup = async ({ email, password, nickname, hashtags } : UserSignup) => { -// const { data } = await axiosInstance.post(`/signup`, { -// email, -// password, -// nickname, -// hashtags, -// }); -// return data; -// }; - -import axios from 'axios'; - -export const postSignup = async () => { - try { - const response = await axios.post('https://api.hmaster.shop/api/v1/signup', { - email: 'ekos555@naver.com', - password: 'asfa1234!@', - nickname: 'rael', - hashtags: ['๋ด„', 'ํŒจ์…˜', '์ฒญ์†Œ', '์š”๋ฆฌ', '์žฌํ™œ์šฉ', '์ฃผํƒ'] - }, { - headers: { - 'Content-Type': 'application/json' - } - }); - console.log('ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต:', response.data); - } catch (error) { - console.error('ํšŒ์›๊ฐ€์ž… ์˜ค๋ฅ˜:', error); - } +export const postSignup = async ({ email, password, nickname, hashtags }: UserSignup) => { + const { data } = await axiosInstance.post(`/signup`, { + email, + password, + nickname, + hashtags, + }); + return data; }; diff --git a/umc-master/src/apis/axios-instance.ts b/umc-master/src/apis/axios-instance.ts index 6afb7ac..5add23a 100644 --- a/umc-master/src/apis/axios-instance.ts +++ b/umc-master/src/apis/axios-instance.ts @@ -1,11 +1,12 @@ -import RoutePaths from '@router/routePaths'; import { useTokenStore } from '@store/tokenStore'; import axios, { AxiosInstance } from 'axios'; +const { accessToken } = useTokenStore.getState(); + const axiosInstance: AxiosInstance = axios.create({ headers: { accept: 'application/json', - Authorization: `Bearer ${import.meta.env.VITE_ACCESS_TOKEN}`, + Authorization: `Bearer ${accessToken}`, }, baseURL: import.meta.env.VITE_BASE_URL, }); @@ -69,11 +70,6 @@ axiosInstance.interceptors.response.use( console.error('ํ† ํฐ ๊ฐฑ์‹  ์‹คํŒจ:', refreshError); useTokenStore.getState().clearTokens(); - // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ - if (window.location.pathname !== RoutePaths.LOGIN) { - window.location.href = RoutePaths.LOGIN; - } - return Promise.reject(refreshError); } } diff --git a/umc-master/src/components/Auth/AuthWrapper.tsx b/umc-master/src/components/Auth/AuthWrapper.tsx new file mode 100644 index 0000000..933ab93 --- /dev/null +++ b/umc-master/src/components/Auth/AuthWrapper.tsx @@ -0,0 +1,30 @@ +import { useEffect } from 'react'; +import { useNavigate, useLocation } from 'react-router-dom'; +import { useTokenStore } from '@store/tokenStore'; +import RoutePaths from '@router/routePaths'; + +interface AuthWrapperProps { + children: React.ReactNode; +} + +const AuthWrapper = ({ children }: AuthWrapperProps) => { + const navigate = useNavigate(); + const location = useLocation(); + const { accessToken } = useTokenStore.getState(); + + useEffect(() => { + // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹ˆ๊ณ  ํ† ํฐ์ด ์—†๋Š” ๊ฒฝ์šฐ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ + if (!accessToken && location.pathname !== RoutePaths.LANDING) { + navigate(RoutePaths.LOGIN, { replace: true }); + } + }, [accessToken, location.pathname, navigate]); + + // ํ† ํฐ์ด ์—†๊ณ  ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์•„๋ฌด๊ฒƒ๋„ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์Œ + if (!accessToken && location.pathname !== RoutePaths.LOGIN) { + return null; + } + + return <>{children}; +}; + +export default AuthWrapper; diff --git a/umc-master/src/components/Modal/profile.tsx b/umc-master/src/components/Modal/profile.tsx index 0c0d5ed..5f4d3d2 100644 --- a/umc-master/src/components/Modal/profile.tsx +++ b/umc-master/src/components/Modal/profile.tsx @@ -14,16 +14,17 @@ import { getUsers } from '@apis/profileApi'; interface ProfileModalProps { isOpen: boolean; onClose: () => void; + profileImage: string; } -const ProfileModal: React.FC = ({ isOpen, onClose }) => { +const ProfileModal: React.FC = ({ isOpen, onClose, profileImage }) => { if (!isOpen) return null; const navigate = useNavigate(); const { clearAuth } = useAuthStore(); const { user, fetchUser } = useUserStore(); useEffect(() => { - fetchUser(); // ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ ์‹œ ์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ + fetchUser(); }, []); getUsers(); @@ -39,7 +40,7 @@ const ProfileModal: React.FC = ({ isOpen, onClose }) => { - + {user?.nickname} ๋‹˜ @@ -109,7 +110,7 @@ const ProfileWrapper = styled.div` padding: 20px 0; `; -const ProfileImage = styled.div` +const ProfileImage = styled.img` width: 60px; height: 60px; border-radius: 50%; @@ -138,7 +139,6 @@ const MenuItem = styled.li` } `; -// "๋งˆ์ดํŽ˜์ด์ง€" ๋งํฌ ์ „์šฉ ์ปดํฌ๋„ŒํŠธ const MenuItemLink = styled(Link)` display: flex; align-items: center; diff --git a/umc-master/src/components/NavigationBar/NavigationBar.tsx b/umc-master/src/components/NavigationBar/NavigationBar.tsx index 9846272..698f53a 100644 --- a/umc-master/src/components/NavigationBar/NavigationBar.tsx +++ b/umc-master/src/components/NavigationBar/NavigationBar.tsx @@ -26,6 +26,10 @@ const NavigationBar: React.FC = ({ login }) => { }, []); getUsers(); + const handleNavClick = () => { + window.scrollTo(0, 0); + }; + const toggleAlarmModal = () => setIsAlarmModalOpen((prev) => !prev); const toggleProfileModal = () => setIsProfileModalOpen((prev) => !prev); @@ -33,15 +37,23 @@ const NavigationBar: React.FC = ({ login }) => { - + ); }; diff --git a/umc-master/src/pages/auth/SignUpPage.tsx b/umc-master/src/pages/auth/SignUpPage.tsx index 48f542f..0036ff2 100644 --- a/umc-master/src/pages/auth/SignUpPage.tsx +++ b/umc-master/src/pages/auth/SignUpPage.tsx @@ -43,15 +43,17 @@ const handleNicknameChange = (nickname: string) => { }; const handleHashtagChange = (hashtags: string[]) => { - setHashtag(hashtags); + const hashtagStrings = hashtags.map(hashtag => hashtag.toString()); + setHashtag(hashtagStrings); }; const handleSignUpComplete = async () => { try { const userSignupData = { email, password, nickname, hashtags }; console.log("ํšŒ์›๊ฐ€์ž… ํ™•์ธ:", userSignupData) - await postSignup(); - navigate("/main"); + await postSignup(userSignupData); + alert("ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต!"); + navigate("/login"); } catch (error) { console.error("ํšŒ์›๊ฐ€์ž… ์˜ค๋ฅ˜:", error); alert("ํšŒ์›๊ฐ€์ž…์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”."); diff --git a/umc-master/src/pages/auth/Signup_components/AgreementForm.tsx b/umc-master/src/pages/auth/Signup_components/AgreementForm.tsx index f0eff45..96c3573 100644 --- a/umc-master/src/pages/auth/Signup_components/AgreementForm.tsx +++ b/umc-master/src/pages/auth/Signup_components/AgreementForm.tsx @@ -3,7 +3,7 @@ import Typography from "@components/common/typography"; import styled, { useTheme } from "styled-components"; import ImgAdd from "@assets/add.svg"; import ImgRemove from "@assets/remove.svg"; -import { useEffect, useState } from "react"; +import { useState } from "react"; interface AgreementItemProps { isRequired: boolean; // ํ•„์ˆ˜ ์—ฌ๋ถ€ @@ -67,10 +67,14 @@ const AgreementForm: React.FC = ({ onCheckRequired }) => { }); // ์ „์ฒด ๋™์˜ ์ฒดํฌ๋ฐ•์Šค - const handleAllAgreeChange = (checked: boolean) => { - setIsAllAgreed(checked); + const handleAllAgreeChange = () => { + const newCheckedState = !isAllAgreed; + setIsAllAgreed(newCheckedState); const updatedItems = { - terms: checked, privacy: checked, thirdinfo: checked, marketing: checked, + terms: newCheckedState, + privacy: newCheckedState, + thirdinfo: newCheckedState, + marketing: newCheckedState, }; setCheckedItems(updatedItems); onCheckRequired(updatedItems.terms && updatedItems.privacy); @@ -79,22 +83,13 @@ const AgreementForm: React.FC = ({ onCheckRequired }) => { const handleCheckboxChange = (key: string, checked: boolean) => { setCheckedItems((prevState) => { const updatedItems = { ...prevState, [key]: checked }; + const allChecked = Object.values(updatedItems).every(Boolean); + setIsAllAgreed(allChecked); onCheckRequired(updatedItems.terms && updatedItems.privacy); return updatedItems; }); }; - useEffect(() => { - if (isAllAgreed) { - setCheckedItems({ - terms: true, privacy: true, thirdinfo: true, marketing: true, - }); - onCheckRequired(true); - } else { - onCheckRequired(checkedItems.terms && checkedItems.privacy); - } - }, [isAllAgreed, checkedItems, onCheckRequired]); - return ( (false); const [verified, setVerified] = useState(false); const [timer, setTimer] = useState(180); - const [retryEnabled, setRetryEnabled] = useState(false); + const [isEmailDuplicate, setIsEmailDuplicate] = useState(false); const fullEmail = localPart && domain ? `${localPart}@${domain}` : ""; @@ -49,9 +49,7 @@ const EmailForm: React.FC<{ timerInterval = setInterval(() => { setTimer((prev) => prev - 1); }, 1000); - } else if (timer === 0) { - setRetryEnabled(true); - } + } return () => { if (timerInterval) { clearInterval(timerInterval); @@ -103,6 +101,8 @@ const EmailForm: React.FC<{ onEmailChange(updatedFullEmail); console.log("๋„๋ฉ”์ธ ๋ณ€๊ฒฝ:", updatedFullEmail); + + setIsEmailDuplicate(false); // ์ค‘๋ณต ํ™•์ธ ๋ฒ„ํŠผ์„ ๋‹ค์‹œ ํ™œ์„ฑํ™” }; const handleEmailChange = (e: React.ChangeEvent) => { @@ -113,8 +113,26 @@ const EmailForm: React.FC<{ onEmailChange(updatedFullEmail); console.log("์ด๋ฉ”์ผ ์ž…๋ ฅ:", updatedFullEmail); + + setIsEmailDuplicate(false); // ์ค‘๋ณต ํ™•์ธ ๋ฒ„ํŠผ์„ ๋‹ค์‹œ ํ™œ์„ฑํ™” }; + // ์ด๋ฉ”์ผ ์ค‘๋ณต ์ฒดํฌ + const checkEmailDuplicate = async () => { + if (!fullEmail) { + alert("์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."); + return; + } + try { + const response = await axiosInstance.post("/check-email", { email: fullEmail }); + if (response.data.isSuccess) { + setIsEmailDuplicate(true); + alert("์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค."); + } + } catch (error) { + alert("์ด๋ฉ”์ผ์ด ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."); + } + }; const handleRetry = () => { setLocalPart(""); @@ -123,7 +141,6 @@ const EmailForm: React.FC<{ setEmailSent(false); setVerified(false); setTimer(180); - setRetryEnabled(false); }; return ( @@ -147,7 +164,7 @@ const EmailForm: React.FC<{ {emails.map((email) => ( ))} - @@ -175,7 +200,7 @@ const EmailForm: React.FC<{ variant="titleXxxSmall" style={{color: theme.colors.red[500]}} >๋‚จ์€ ์‹œ๊ฐ„: {Math.floor(timer / 60)}๋ถ„ {timer % 60}์ดˆ - diff --git a/umc-master/src/pages/auth/Signup_components/PasswordForm.tsx b/umc-master/src/pages/auth/Signup_components/PasswordForm.tsx index 0de5716..01ebcf3 100644 --- a/umc-master/src/pages/auth/Signup_components/PasswordForm.tsx +++ b/umc-master/src/pages/auth/Signup_components/PasswordForm.tsx @@ -1,6 +1,8 @@ /* eslint-disable react/prop-types */ import Typography from "@components/common/typography"; import Input from "@components/Input/Input"; +import useInput from "@hooks/useInput"; +import { validatePasswordFormat } from "@utils/validation"; import { useEffect, useState } from "react"; import { styled, useTheme } from "styled-components"; @@ -13,11 +15,40 @@ const PasswordForm: React.FC<{ const theme = useTheme(); - const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); + const [passwordErrorMessage, setPasswordErrorMessage] = useState(''); + const [confirmPasswordErrorMessage, setConfirmPasswordErrorMessage] = useState(''); + const [isPasswordValid, setIsPasswordValid] = useState(false); + + // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ + const { + input: password, + errorMessage: passwordInputErrorMessage, + changeHandler: passwordChangeHandler, + } = useInput({ + initialValue: "", + validate: async (value) => { + const error = validatePasswordFormat(value); + setIsPasswordValid(!error); // ํ˜•์‹์ด ๋งž์œผ๋ฉด true, ์•„๋‹ˆ๋ฉด false + return error; + } + }); + + // ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ณ€๋™ + useEffect(() => { + if (confirmPassword && password !== confirmPassword) { + setConfirmPasswordErrorMessage("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); + } else { + setConfirmPasswordErrorMessage(""); + } + }, [confirmPassword, password]); + + useEffect(() => { + setPasswordErrorMessage(passwordInputErrorMessage || ""); + }, [passwordInputErrorMessage]); useEffect(() => { - if (password && confirmPassword && password === confirmPassword) { + if (isPasswordValid && confirmPassword && password === confirmPassword) { onCheckRequired(true); } else { onCheckRequired(false); @@ -26,8 +57,8 @@ const PasswordForm: React.FC<{ const handlePasswordChange = (e: React.ChangeEvent) => { const newPassword = e.target.value; - setPassword(newPassword); onPasswordChange(newPassword); // ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ + passwordChangeHandler(e); console.log("๋น„๋ฐ€๋ฒˆํ˜ธ: ", newPassword); }; @@ -38,14 +69,14 @@ const PasswordForm: React.FC<{ style={{color: theme.colors.primary[700]}} >๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ (ํ•„์ˆ˜) * void; }> = ({ onCheckRequired, onNicknameChange }) => { + const theme = useTheme(); + + const [profileImageUrl, setProfileImageUrlLocal] = useState(gray_character); const [selectedCity, setSelectedCity] = useState("default"); const [districts, setDistricts] = useState([]); - const [nickname, setNickname] = useState(""); + const [errorMessage, setErrorMessage] = useState(""); // ๋‹‰๋„ค์ž„ ์ž…๋ ฅ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜ const handleNicknameChange = (e: React.ChangeEvent) => { const newNickname = e.target.value; setNickname(newNickname); - onNicknameChange(newNickname); // ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์—…๋ฐ์ดํŠธ - console.log("๋‹‰๋„ค์ž„: ", newNickname); - // ๋‹‰๋„ค์ž„์ด 0๊ธ€์ž ์ด์ƒ์ผ ๋•Œ๋งŒ "๋‹ค์Œ" ๋ฒ„ํŠผ์„ ํ™œ์„ฑํ™” - onCheckRequired(newNickname.length > 0); + onNicknameChange(newNickname); + const nicknameRegex = /^[a-zA-Z0-9ใ„ฑ-ใ…Ž๊ฐ€-ํžฃ._]+$/; + + if (newNickname.length === 0) { + setErrorMessage("๋‹‰๋„ค์ž„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."); + onCheckRequired(false); + } else if (newNickname.length > 11) { + setErrorMessage("๋‹‰๋„ค์ž„์„ ์ตœ๋Œ€ 10์ž๊นŒ์ง€ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."); + onCheckRequired(false); + } else if (!nicknameRegex.test(newNickname)) { + setErrorMessage("๋‹‰๋„ค์ž„์€ ํ•œ๊ธ€, ์˜๋ฌธ, ์ˆซ์ž, '.', '_' ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."); + onCheckRequired(false); + } else { + setErrorMessage(""); + onCheckRequired(true); + } }; // ๋„์‹œ ์„ ํƒ์‹œ ๊ตฌ ๋ชฉ๋ก์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜ @@ -90,17 +106,34 @@ const PrivacyForm: React.FC<{ break; } }; - - const theme = useTheme(); + + const handleImageChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + const imageUrl = reader.result as string; + setProfileImageUrlLocal(imageUrl); // ๋กœ์ปฌ ์ƒํƒœ ์—…๋ฐ์ดํŠธ + // api ์—ฐ๊ฒฐ + }; + reader.readAsDataURL(file); + } + }; + return ( - ํ”„๋กœํ•„ ์‚ฌ์ง„ (์„ ํƒ) - - + + document.getElementById('fileInput')?.click()} + /> + @@ -109,6 +142,7 @@ const PrivacyForm: React.FC<{ style={{color: theme.colors.primary[700]}} >๋‹‰๋„ค์ž„ (ํ•„์ˆ˜) * = ({ sectionCount }) => { {step} @@ -51,7 +52,7 @@ const Sequence = styled.div` position: relative; display: flex; align-items: center; - gap: 160px; + gap: 130px; ` const Step = styled.div` @@ -85,7 +86,7 @@ const Num = styled.div<{ isActive: boolean }>` const Line = styled.div` position: absolute; top: 30px; - left: 5px; + left: 15px; width: 99%; height: 1px; border: 1px dotted ${({ theme }) => theme.colors.text.lightGray}; diff --git a/umc-master/src/pages/community/components/Banner.tsx b/umc-master/src/pages/community/components/Banner.tsx index fa9a931..ab7e77f 100644 --- a/umc-master/src/pages/community/components/Banner.tsx +++ b/umc-master/src/pages/community/components/Banner.tsx @@ -38,4 +38,5 @@ const TipCreateBTN = styled.button` border-radius: 50px; margin-top: 24px; color: ${({ theme }) => theme.colors.text['black']}; + cursor: pointer; `; diff --git a/umc-master/src/pages/saveTip/SaveTipPage.tsx b/umc-master/src/pages/saveTip/SaveTipPage.tsx index 2641d3b..a877484 100644 --- a/umc-master/src/pages/saveTip/SaveTipPage.tsx +++ b/umc-master/src/pages/saveTip/SaveTipPage.tsx @@ -80,8 +80,8 @@ const SaveTipPage: React.FC = () => { : placeholderImg } text={item.title} - likes={item.likes ?? 0} - bookmarks={item.bookmarks ?? 0} + likes={item.likeCount ?? 0} + bookmarks={item.saveCount ?? 0} date={item.createdAt.slice(0, 10)} onClick={() => handleCardClick(item.tipId)} /> diff --git a/umc-master/src/pages/saveTip/components/PostDetail.tsx b/umc-master/src/pages/saveTip/components/PostDetail.tsx index c9e1460..6af68ab 100644 --- a/umc-master/src/pages/saveTip/components/PostDetail.tsx +++ b/umc-master/src/pages/saveTip/components/PostDetail.tsx @@ -45,7 +45,19 @@ const PostDetail: React.FC = ({ detail }) => { return ( - {detail.media.length > 0 && ๊ฒŒ์‹œ๋ฌผ ์ด๋ฏธ์ง€} + {detail.media.length > 0 && ( + + {detail.media.map((item, index) => ( + + ))} + + )} {detail.title} @@ -98,14 +110,78 @@ const PostView = styled.div` align-self: stretch; `; -const Img = styled.img` +const ImageGrid = styled.div<{ count: number }>` + display: grid; width: 80vw; - height: 360px; + gap: 10px; + + ${({ count }) => + count === 1 + ? `grid-template-columns: 1fr; + grid-auto-rows: 360px;` + : count === 2 + ? `grid-template-columns: 1fr 1fr; + grid-auto-rows: 360px;` + : count === 3 + ? `grid-template-columns: repeat(3, 1fr);` + : count === 4 + ? ` + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: auto auto; + grid-template-areas: + "left top right" + "left bottom right"; + ` + : count === 5 + ? ` + display: grid; + grid-template-columns: 1fr 1fr 1fr; + & > :nth-child(4), & > :nth-child(5) { + grid-column: span 1; + } + ` + : `grid-template-columns: repeat(3, 1fr);`} + + grid-auto-rows: minmax(180px, auto); +`; + +const ImageItem = styled.img<{ index: number; count: number }>` + width: 100%; border-radius: 20px; object-fit: cover; - background: #d9d9d9; -`; + ${({ count, index }) => + count === 1 + ? `height: 360px;` + : count === 4 + ? index === 0 + ? `grid-area: left; grid-row: span 2; height: 360px;` + : index === 1 + ? `grid-area: top; height: 175px;` + : index === 2 + ? `grid-area: bottom; height: 175px;` + : index === 3 + ? `grid-area: right; grid-row: span 2; height: 360px;` + : '' + : // TODO: ์ˆ˜์ • + // count === 5 + // ? index === 0 + // ? `grid-area: left; grid-row: span 2; height: 360px;` + // : index === 1 + // ? `grid-area: top; height: 175px;` + // : index === 2 + // ? `grid-area: bottom-left; grid-column: span 1; height: 175px;` + // : index === 3 + // ? `grid-area: bottom-right; grid-column: span 1; height: 175px;` + // : index === 4 + // ? `grid-area: right; grid-row: span 2; height: 360px;` + // : '' + count === 5 + ? index < 3 + ? `grid-column: span 1; height: 360px;` + : `grid-column: span 2; height: 360px;` + : `aspect-ratio: 16/9;`} +`; const PostInfo = styled.div` display: flex; justify-content: space-between; diff --git a/umc-master/src/router/routes.tsx b/umc-master/src/router/routes.tsx index d87d993..854b969 100644 --- a/umc-master/src/router/routes.tsx +++ b/umc-master/src/router/routes.tsx @@ -20,6 +20,39 @@ import ChatPage from '@pages/chat/ChatPage'; import ErrorPage from '@pages/error/ErrorPage'; import MyChallengePage from '@pages/mychallenge/MyChallenge'; import ChallengeDetailPage from '@pages/challenge/ChallengeDetailPage'; +import AuthWrapper from '@components/Auth/AuthWrapper'; + +// ์ธ์ฆ์ด ํ•„์š”ํ•œ ๋ผ์šฐํŠธ๋“ค์„ ๋ฐฐ์—ด๋กœ ์ •์˜ +const protectedRoutes = [ + { path: RoutePaths.MYPAGE, element: }, + { path: RoutePaths.MAIN, element: }, + { path: RoutePaths.SAVE_TIP, element: }, + { path: RoutePaths.SEARCH, element: }, + { path: RoutePaths.SAVE_TIP_DETAIL, element: }, + { path: RoutePaths.CREATE_POST, element: }, + { path: RoutePaths.COMMUNITY, element: }, + { path: RoutePaths.MAGAZINE, element: }, + { path: RoutePaths.MAGAZINE_DETAIL, element: }, + { path: RoutePaths.CHALLENGE, element: }, + { path: RoutePaths.MYCHALLENGE, element: }, + { path: RoutePaths.CHALLENGE_DETAIL, element: }, + { path: RoutePaths.CHAT, element: }, +]; + +// ์ธ์ฆ์ด ํ•„์š”์—†๋Š” public ๋ผ์šฐํŠธ๋“ค +const publicRoutes = [ + { index: true, element: }, + { path: RoutePaths.LOGIN, element: }, + { path: RoutePaths.SIGNUP, element: }, + { path: RoutePaths.FINDPRIVACY, element: }, + { path: RoutePaths.KAKAO_CALLBACK, element: }, +]; + +// protected ๋ผ์šฐํŠธ๋“ค์„ AuthWrapper๋กœ ๊ฐ์‹ธ๊ธฐ +const wrappedProtectedRoutes = protectedRoutes.map((route) => ({ + ...route, + element: {route.element}, +})); const router = createBrowserRouter([ { @@ -28,26 +61,7 @@ const router = createBrowserRouter([ children: [ { errorElement: , - children: [ - { index: true, element: }, - { path: RoutePaths.LOGIN, element: }, - { path: RoutePaths.SIGNUP, element: }, - { path: RoutePaths.FINDPRIVACY, element: }, - { path: RoutePaths.MYPAGE, element: }, - { path: RoutePaths.MAIN, element: }, - { path: RoutePaths.SEARCH, element: }, - { path: RoutePaths.SAVE_TIP, element: }, - { path: RoutePaths.SAVE_TIP_DETAIL, element: }, - { path: RoutePaths.CREATE_POST, element: }, - { path: RoutePaths.COMMUNITY, element: }, - { path: RoutePaths.MAGAZINE, element: }, - { path: RoutePaths.MAGAZINE_DETAIL, element: }, - { path: RoutePaths.KAKAO_CALLBACK, element: }, - { path: RoutePaths.CHALLENGE, element: }, - { path: RoutePaths.MYCHALLENGE, element: }, - { path: RoutePaths.CHALLENGE_DETAIL, element: }, - { path: RoutePaths.CHAT, element: }, - ], + children: [...publicRoutes, ...wrappedProtectedRoutes], }, ], }, diff --git a/umc-master/src/store/tokenStore.ts b/umc-master/src/store/tokenStore.ts index 3f894cc..b06adaf 100644 --- a/umc-master/src/store/tokenStore.ts +++ b/umc-master/src/store/tokenStore.ts @@ -9,7 +9,7 @@ interface TokenStore { export const useTokenStore = create((set) => ({ accessToken: null, - refreshToken: `${import.meta.env.VITE_REFRESH_TOKEN}` /* ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ์™„์„ฑ ํ›„ ์ˆ˜์ • ์˜ˆ์ •์ž„ */, + refreshToken: null /* ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ์™„์„ฑ ํ›„ ์ˆ˜์ • ์˜ˆ์ •์ž„ */, setTokens: (tokens) => { // console.log('Setting Tokens:', tokens); set(() => ({ From 8cca994f05b84a611f583a29e48e4783b01199dd Mon Sep 17 00:00:00 2001 From: Minji Kim <68258295+minzee09@users.noreply.github.com> Date: Fri, 21 Feb 2025 06:35:25 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[DEPLOY]=205=EC=B0=A8=20=EB=B0=B0=ED=8F=AC?= =?UTF-8?q?=20(#103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * โœจ feat: MainPage Banner UI ๊ตฌํ˜„ * ๐Ÿ’„ UI: Banner padding ์ˆ˜์ • # 11 * โœจ feat: QuizBox ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * โœจ feat: SearchBar ๊ตฌํ˜„ #11 * โœจ feat: Categories ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * ๐Ÿ”ง config: Font Awesome ์„ค์น˜ #11 * ๐Ÿ’„ UI: categories ์•„๋ž˜ ํ™”์‚ดํ‘œ ์ถ”๊ฐ€ #11 * โœจ feat : TipsSection ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * โœจ feat: LoginPage Title&Input UI ๊ตฌํ˜„ #10 * โœจ feat: LoginPage LoginOptions UI ๊ตฌํ˜„ #10 * โœจ feat: LoginPage LoginButton UI ๊ตฌํ˜„ #10 * โ™ป๏ธ refactor: LoginPage Title component #10 * โ™ป๏ธ refactor: LoginPage Title component #10 * โ™ป๏ธ refactor: LoginPage ButtonBox component #10 * โ™ป๏ธ refactor: LoginPage InputForm component #10 * ๐Ÿ’„ UI : TipsSectionTopFive ์ค‘๋ณต ์‚ญ์ œ #11 * ๐Ÿ’„ UI : Card Component ๋ถ„๋ฆฌ ์ž‘์—… #11 * ๐Ÿ’„ UI : SearchBar/ Card ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #11 * ๐Ÿ”ง config: CI ๊ฒฝ๋กœ ์ˆ˜์ • #7 * ๐Ÿ”ง config: cwd ์ถ”๊ฐ€ #7 * ๐Ÿ”ง config: ๋ผ์šฐํŒ… ๋™์ž‘ ์œ„ํ•œ ํŒŒ์ผ ์ถ”๊ฐ€ #7 * ๐Ÿ’„ UI: LoginPage KakaoLogin Button ์ˆ˜์ • #10 * ๐Ÿ’„ UI: LoginPage UI์‚ฌ์ด์ฆˆ ์ถ•์†Œ #10 * ๐Ÿ’„ UI: LoginPage UI์‚ฌ์ด์ฆˆ ํ™•๋Œ€ (Figma Size) #10 * โœจ feat: add MyPage router #16 * โœจ feat: MyPage Title&์ƒ๋‹จ์นด๋“œ ๊ตฌํ˜„ํ˜„ #16 * โœจ feat: MyPage ํ”„๋กœํ•„ ๋ณ€๊ฒฝ ๋ฒ„ํŠผ ์ถ”๊ฐ€๊ฐ€ #16 * ๐Ÿ”ง config: eslint ๊ทœ์น™ ์ œ๊ฑฐ #12 * ๐Ÿ“ฆ package: add react-icons #12 * ๐ŸŽจ styles: update reset.css file #12 * ๐Ÿ’„ UI: add logo image #12 * โœจ feat: ํ—ค๋” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #12 * โœจ feat: ํ‘ธํ„ฐ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #12 * ๐Ÿ’„ UI: ํ—ค๋” ํ‘ธํ„ฐ ๋ ˆ์ด์•„์›ƒ ์ถ”๊ฐ€ #12 * โœจ feat: MyPage ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ถ”๊ฐ€ & ์นด๋“œ ์ปดํฌ๋„ŒํŠธ #16 * โœ๏ธ typo: MyPage GoodTip->RecnetGoodTip์œผ๋กœ ์ˆ˜์ •์ • #16 * โœจ feat: MyPage Best ๊ฟ€ํŒ ์„ ์ • ํšŸ์ˆ˜ & ๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ ์ปดํฌ๋„ŒํŠธ #16 * โ™ป๏ธ refactor: MyPage ProfileSection ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage RecentTips ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage dummyData ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage BestInterest ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage ์ด์Šˆ๋ฒˆํ˜ธ ์ˆ˜์ •์ • #16 * ๐Ÿ’„ UI: MyPage ์ปดํฌ๋„ŒํŠธ ์œ„์น˜ ์ˆ˜์ • #16 * ๐Ÿ“ฆ package: add framer-motion #12 * ๐ŸŽจ style: ์„ ๋ฌผ์ƒ์ž, ํŠธ๋กœํ”ผ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #12 * โœจ feat: ์Šคํฌ๋กค ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ›… ์ถ”๊ฐ€ #12 * โœจ feat: add LandingPage #12 * ๐Ÿ’„ UI : Card CSS ์ค‘๋ณต ์ œ๊ฑฐ #19 * ๐Ÿ’„ UI : dummy Image ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI : max-width -> min-width ์ˆ˜์ • #19 * ๐Ÿ’„ UI : SearchSection ์ปดํฌ๋„ŒํŠธ ์„ธ๋ถ„ํ™” ๋ฐ CSS ์ˆ˜์ • #19 * ๐Ÿ’„ UI : TipSection Props ํ˜•์‹ ์ˆ˜์ • #19 * ๐Ÿ’„ UI : Search Bar ๊ณต์šฉ ์‚ฌ์šฉ์œผ๋กœ ์ธํ•œ CSS ์ˆ˜์ • #19 * ๐Ÿ’„ UI : ๊ณต์šฉ BigCard ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI : SearchPage ๊ตฌํ˜„ #19 * ๐Ÿ’„ UI : SearchPage Recommended Title ์ปดํฌ๋„ŒํŠธ #19 * ๐Ÿ’„ UI : SearchPage TipSection ๊ตฌํ˜„ #19 * ๐Ÿ’„ UI : dummyImage MainPage์— ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI: LoginPage Input.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ ๋ฐ Style ์ˆ˜์ • #10 * โ™ป๏ธ refactor: LoginPage Button.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * ๐Ÿ’„ UI : Button ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #10 * ๐Ÿ’„ UI : Input ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage InterestTag.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #16 * โ™ป๏ธ refactor: MyPage Section.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #16 * ๐Ÿ’„ UI : InterestTag ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #16 * ๐Ÿ”ฅ remove: isAuth ์‚ญ์ œ #12 * โœจ feat: add font #22 * โœจ feat: add themeProvider #22 * โœจ feat: add globalStyle #22 * โœจ feat: add typography #22 * โ™ป๏ธย refactor: kakao_login ์ด๋ฏธ์ง€ ํŒŒ์ผ ์œ„์น˜ ๋ณ€๊ฒฝ #10 * โ™ป๏ธย refactor: <> ์‚ญ์ œ #10 * โœ๏ธย typo: ํด๋” ์ด๋ฆ„ ๋ณ€๊ฒฝ (MyPage_components -> components) #16 * โœ๏ธย typo: ์˜คํƒ€ ์ˆ˜์ • (ProfileCard2 -> ProfileCard) #16 * โ™ป๏ธ refactor: <> ์‚ญ์ œ #16 * โ™ป๏ธ refactor: import ๊ฒฝ๋กœ๋ฅผ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋กœ ๋ณ€๊ฒฝ #16 * โ™ป๏ธ refactor : keypress -> keydown ์œผ๋กœ ์ˆ˜์ • #19 * โ™ป๏ธ refactor : text1, text2 ์ˆซ์ž ์‚ฌ์šฉ front, backText ๋กœ ์ˆ˜์ • #19 * ๐Ÿ”ง config: package-lock ํŒŒ์ผ ์‚ญ์ œ * ๐Ÿ’„ UI: modify logo image file #25 * โœจ feat: ์ถ”๊ฐ€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜ #22 * โœจ feat: ์ถ”๊ฐ€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ํƒ€์ดํฌ ๋ฐ˜์˜ #22 * ๐Ÿ’„ UI: Title ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: LoginPage ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ“ฆ package: add vite-plugin-svgr #25 * ๐Ÿ”ง config: svg ์‚ฌ์šฉ ์œ„ํ•œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ์„ค์ • #25 * ๐Ÿ’„ UI: ์•Œ๋ฆผ ์•„์ดํ†ค ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: update Navigation Bar #25 * โœ๏ธ Typo: todo ํ…์ŠคํŠธ ์ค‘๋ณต ์‚ญ์ œ #25 * ๐Ÿ’„ UI: Input ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: Button ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: LoginPage ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„UI: logo ์•„์ด์ฝ˜ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: ํ‘ธํ„ฐ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜ #25 * โœจ feat: SignupPage ๊ตฌ์กฐ #21 * โœจ feat: ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ๊ณ ์ • #25 * โœจ feat: ํ”„๋กœํ•„ ์•„๋ฐ”ํƒ€ ์ƒ์„ฑ #21 * โœจ feat: ํ”„๋กœํ•„ ์ถ”๊ฐ€ ๋ฒ„ํŠผ #21 * ๐Ÿ”ง config: design system ์ถ”๊ฐ€ #24 * ๐Ÿ’„ UI: Tag ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #24 * ๐Ÿ’„ UI: Card ์ปดํฌ๋„ŒํŠธ ๋””์ž์ธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Banner UI ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Search UI ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Quiz ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: TipSection ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Category ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: MainPage ์ˆ˜์ • #24 * โœจ feat: ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€ #21 * ๐ŸŽจ style: alarm ์•„์ด์ฝ˜ ์ˆ˜์ • #25 * ๐Ÿ’„ UI: close icon ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: SearchSection margin ์ˆ˜์ • #24 * ๐Ÿ’„ UI: BigCard ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: SearchPage Tip ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์ˆ˜์ • #24 * โœจ feat: add alarm modal #25 * ๐Ÿ’„ UI: Banner UI ์ˆ˜์ • #24 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #25 * ๐Ÿ’„ UI: SavedTipSection Card Props ์ˆ˜์ • #24 * โ™ป๏ธ refactor: pํƒœ๊ทธ ์˜ค๋ฅ˜ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Design System ์ ์šฉ #24 * โ™ป๏ธ refactor: Console์˜ค๋ฅ˜ props attr DOM ๋žœ๋”๋ง ํ•ด๊ฒฐ #24 * ๐Ÿ’„ UI: errorMessage ์Šคํƒ€์ผ ์ถ”๊ฐ€ (๋นจ๊ฐ„ ํ…Œ๋‘๋ฆฌ) #34 * ๐Ÿ”ง config: ์—๋Ÿฌํ•ธ๋“ค๋ง์„ ์œ„ํ•œ useInput ์ปค์Šคํ…€ํ›… ์ถ”๊ฐ€ #34 * โœจ feat: ์ด๋ฉ”์ผ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ #34 * ๐Ÿ”ง config: ์ด๋ฉ”์ผ ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•œ validation ์ƒ์„ฑ #34 * ๐Ÿ“ฆ package: axios ์ถ”๊ฐ€ #34 * ๐Ÿ”ง config: errorHandler ์‚ญ์ œ์ œ #34 * โ™ป๏ธ refactor: ButtonBox ์‚ญ์ œ ํ›„ InputForm์— ํ•ฉ์น˜๊ธฐ๊ธฐ #34 * โœจ feat: ์ž๋™๋กœ๊ทธ์ธ ํด๋ฆญ ์‹œ ์ฒดํฌ๋ฐ•์Šค ํ™œ์„ฑํ™” #34 * Feat/#33 UI community page UI & CreateAndPostPage UI (#37) * ๐Ÿ’„ UI: recent/ likes / bookmarks ๊ธฐ๋Šฅ ์ˆ˜์ • #33 * ๐Ÿ’„ UI: Community Page Banner Component #33 * ๐Ÿ’„ UI: Community Page 1 ๊ตฌํ˜„ #33 * ๐Ÿ”ง config: --host ์ถ”๊ฐ€ #33 * ๐Ÿ’„ UI: plus ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #33 * ๐Ÿ’„ UI: Tag ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #33 * ๐Ÿ’„ UI: ์ด๋ฏธ์ง€ ์—…๋กœ๋” ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: Title ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: CreatePostPage ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: Categories ์ปดํฌ๋„ŒํŠธ ์žฌ์ˆ˜์ • #33 * ๐Ÿ’„ UI: SearchModal ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: SearchSection ์žฌ์ˆ˜์ • #33 * ๐Ÿ’„ UI: SearchModalBar ๊ตฌํ˜„ #33 * ๐Ÿ› fix : error ํ•ด๊ฒฐ๊ฒฐ * ๐Ÿ’„ UI: ํƒ€์ดํ‹€ ๋””์ž์ธ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ๋งˆ์ดํŽ˜์ด์ง€ UI ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: Tag ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: Section ์ปดํฌ๋„ŒํŠธ UI ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ˆ˜์ • ์กฐ๊ฑด๋ถ€ ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์กฐ๊ฑด ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ํ”„๋กœํ•„์นด๋“œ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์กฐ๊ฑด ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํŽธ์ง‘ํ•˜๊ธฐ ๋ฒ„ํŠผ ์ถ”๊ฐ€ #29 * โœจ feat: profileEdit ๋ฒ„ํŠผ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ ๋ฐ onClick ์†์„ฑ ์ถ”๊ฐ€ #29 * โœจ feat: add ProfileEditModal router #29 * ๐Ÿ’„ UI: ๋“œ๋กญ๋‹ค์šด ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #29 * ๐Ÿ“ฆ package: ์ง€์—ญ ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ #29 * โœจ feat: profileEdit ๋ชจ๋‹ฌ ์ƒ์„ฑ #29 * โœจ feat: profileEdit ๋ชจ๋‹ฌ ์—ฐ๊ฒฐ #29 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #29 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #29 * โœ๏ธ Typo: ํ•„์š”์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ #29 * โœจ feat: interestEdit ๋ฒ„ํŠผ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ๋ฒ„ํŠผ padding ์ˆ˜์ • #29 * โœจ feat: interestEdit ๋ชจ๋‹ฌ ์ƒ์„ฑ #29 * โœจ feat: interestEdit ๋ชจ๋‹ฌ ์—ฐ๊ฒฐ #29 * โœจ feat: ๋ชจ๋‹ฌ ์ƒ๋‹จ์— X ๋‹ซ๊ธฐ ๋ฒ„ํŠผ ์ƒ์„ฑ #29 * โœจ feat: add SignUpPage ์ „์ฒด ์ˆ˜์ • #21 * โœจ feat: add SignupState ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ #21 * โœจ feat: button์— pageUp, pageDown, signUp ๋ณ€์ˆ˜ ์ƒ์„ฑ #21 * โœจ feat: Section1 ์•ฝ๊ด€ ๋™์˜ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: button์— disabled ์†์„ฑ ์ƒ์„ฑ #21 * โœจ feat: ํ•„์ˆ˜ ์•ฝ๊ด€ ๋™์˜์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: Button์— disabled ์Šคํƒ€์ผ ์ถ”๊ฐ€ #21 * โœจ feat: + ๋ˆŒ๋ €์„ ๋•Œ ์•ฝ๊ด€ ์ƒ์„ธ ๋‚ด์šฉ ๋„์šฐ๊ธฐ ์ถ”๊ฐ€ #21 * โœจ feat: button์— emailCheck ๋ณ€์ˆ˜ ์ƒ์„ฑ #21 * โœจ feat: Section2 ์ด๋ฉ”์ผ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: Section3 ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * ๐Ÿ’„ UI: ์ œ๋ชฉ ์ƒ‰์ƒ primary[700]์œผ๋กœ ๋ณ€๊ฒฝ #21 * โœจ feat: Section4 ๊ฐœ์ธ์ •๋ณด ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: Section4 ๋‹ค์Œ ๋ฒ„ํŠผ ์ถ”๊ฐ€ ์ˆ˜์ • #21 * โœจ feat: Section5 ๊ด€์‹ฌ์‚ฌ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: ํšŒ์›๊ฐ€์ž… ์™„๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ฉ”์ธํ™”๋ฉด์œผ๋กœ #21 * โœจ feat: Section4 ํ”„๋กœํ•„ ์นด๋ฉ”๋ผ ์ปค์„œ ํฌ์ธํ„ฐ #21 * โœจ feat: ๋‹‰๋„ค์ž„ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: ์ด๋ฉ”์ผ ๋ฐ ์ธ์ฆ๋ฒˆํ˜ธ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœ๏ธ Typo: ์„น์…˜ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ๋ณ€๊ฒฝ #21 * ๐Ÿ’„ UI: ๋ฒ„ํŠผ ๊ธ€์ž์ˆ˜์— ๋งž๊ฒŒ ์„ ํƒ์ƒ์ž ํฌ๊ธฐ ์ˆ˜์ • ๋ฐ font style ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ์ž๋™๋กœ๊ทธ์ธ ์ฒดํฌ๋ฐ•์Šค ์ƒ‰์ƒ ๋ณ€๊ฒฝ #34 * Feat/#38 pagination ๊ตฌํ˜„ & Skeleton UI TipSection (#40) * ๐Ÿ”ง config: .env gitignore ์„ค์ • #38 * ๐Ÿ”ง config: axios, react-query ์„ค์น˜ #38 * ๐Ÿ”ง config: ReactQueryDevtools, queryClient ์„ค์ • #38 * โœจ feat: axios ๊ธฐ๋ณธ hook #38 * ๐Ÿ’„ UI: dummyData ์ƒ์„ฑ #38 * โœจ feat: useGetTips hook ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection Component ์ˆ˜์ • #38 * ๐Ÿ’„ UI: TipsSection Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: Props ๋กœ ์ธํ•œ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * โœจ feat: Pagination ๊ธฐ๋Šฅ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection ํƒ€์ž… ์ถ”๊ฐ€ #38 * โœจ feat: SkeletonCard UI ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: SkeletonBigCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #38 * # UI: RecommendTips ๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: CommunityPage TipSection ์ปดํฌ๋„ŒํŠธ Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: BigCard pํƒœ๊ทธ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * Feat/#46 feat quiz banner (#47) * ๐Ÿ”ง config: .env gitignore ์„ค์ • #38 * ๐Ÿ”ง config: axios, react-query ์„ค์น˜ #38 * ๐Ÿ”ง config: ReactQueryDevtools, queryClient ์„ค์ • #38 * โœจ feat: axios ๊ธฐ๋ณธ hook #38 * ๐Ÿ’„ UI: dummyData ์ƒ์„ฑ #38 * โœจ feat: useGetTips hook ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection Component ์ˆ˜์ • #38 * ๐Ÿ’„ UI: TipsSection Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: Props ๋กœ ์ธํ•œ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * โœจ feat: Pagination ๊ธฐ๋Šฅ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection ํƒ€์ž… ์ถ”๊ฐ€ #38 * โœจ feat: SkeletonCard UI ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: SkeletonBigCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #38 * # UI: RecommendTips ๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: CommunityPage TipSection ์ปดํฌ๋„ŒํŠธ Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: BigCard pํƒœ๊ทธ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * ๐Ÿ”ง config: ์ƒํƒœ๊ด€๋ฆฌ zustand ์„ค์น˜ #41 * ๐Ÿ’„ UI: dummyCategories ํด๋” ์ด๋™ #41 * ๐Ÿ’„ UI: SearchBar Icon ์ˆ˜์ • #41 * ๐Ÿ’„ UI: DummyCat ์ถ”๊ฐ€ #41 * โœจ feat: CreateAndPost Post Api ์—ฐ๋™ #41 * โœจ feat: Complete Modal ๊ตฌํ˜„ #41 * ๐Ÿ”ง config: framer-motion ์„ค์น˜ #46 * ๐Ÿ’„ UI: Icon, character ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #46 * โœจ feat: quiz Store ๊ตฌํ˜„ #46 * ๐Ÿ’„ UI: QuizBox ํ–‰๋™ ๊ตฌํ˜„ #46 * ๐Ÿ”ง config: develop ๋ฌธ์ œ ํ•ด๊ฒฐ #46 * ๐Ÿšจ conflict ํ•ด๊ฒฐ #46 * ๐Ÿ’„ UI: Vecel ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #46 * โœจ feat: kakaocallbackํŽ˜์ด์ง€ ๊ตฌํ˜„ ๋ฐ ๋ผ์šฐํ„ฐ #49 * โœ๏ธ Typo: eslint ๋ฌด์‹œ ๋ฌธ๊ตฌ ์‚ญ์ œ #49 * โœจ feat: ํšŒ์›๊ฐ€์ž… ํด๋ฆญ ์‹œ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ #49 * โœจ feat: ํšŒ์› ์ •๋ณด ์ฐพ๊ธฐ ํŽ˜์ด์ง€ ์ƒ์„ฑ #49 * โœจ feat: ํšŒ์› ์ •๋ณด ์ฐพ๊ธฐ ํŽ˜์ด์ง€ ์—ฐ๊ฒฐ #49 * Feat/#43 UI save tip page (#50) * โœจ feat: SaveTipPage ๊ตฌํ˜„ #43 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ #43 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ณ€๊ฒฝ #43 * โœจ feat: SkeletonImage width 240px๋กœ ๋ณ€๊ฒฝ#43 * โœจ feat: ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„ #43 * โœจ feat: Card ์ปดํฌ๋„ŒํŠธ onClick ์†์„ฑ ์ถ”๊ฐ€ #43 * โœจ feat: ์นด๋“œ ์ปดํฌ๋„ŒํŠธ ํด๋ฆญ ์‹œ ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ #43 * โœจ feat: ๋งˆ์ดํŽ˜์ด์ง€ ์ตœ๊ทผ ๋ณธ ๊ฟ€ํŒ ์ƒ์„ธํŽ˜์ด์ง€ ์—ฐ๊ฒฐ #43 * โœจ feat: onClick ์†์„ฑ์— ?์„ ํƒ ์ถ”๊ฐ€ #43 --------- Co-authored-by: rael * Feat/#54 feat quiz modify and on click add (#56) * โœจ feat: BigCard OnClick ํ•จ์ˆ˜ ๊ตฌํ˜„ #54 * โ™ป๏ธ refactor: Exit Animation ๊ตฌํ˜„ ์™„๋ฃŒ #54 * โœจ feat: RecommedTip OnClick ์—ฐ๊ฒฐ #54 * โœจ feat: Post ์˜ค๋ฅ˜ ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ - ์„œ๋ฒ„ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ํ›„ ๋‹ค์‹œ ์‹œ๋„ ์˜ˆ์ • #54 * Feat/#36 UI magazine (#51) * ๐Ÿ”ง config: framer-motion ๋ฒ„์ „ ์ˆ˜์ • #36 * โœจ feat: add mind-map component #36 * โœจ feat: add card-grid component #36 * โ™ป๏ธ refactor: card์—์„œ cardInfo ๋ถ„๋ฆฌ #36 * ๐Ÿ’„ UI: add MagazinePage #36 * ๐Ÿ’„ UI: add MagazineDetailPage #36 * Feat/#53 api folder stucture (#55) * ๐Ÿ”ง config: framer-motion ๋ฒ„์ „ ์ˆ˜์ • #36 * โœจ feat: add mind-map component #36 * โœจ feat: add card-grid component #36 * โ™ป๏ธ refactor: card์—์„œ cardInfo ๋ถ„๋ฆฌ #36 * ๐Ÿ’„ UI: add MagazinePage #36 * ๐Ÿ’„ UI: add MagazineDetailPage #36 * ๐Ÿ”ฅ remove: index file from api folder #53 * ๐Ÿ”ฅ remove: queries folder from hooks #53 * โœจ feat: tip ๊ด€๋ จ api ํ˜ธ์ถœ ์ถ”๊ฐ€ #53 * โœจ feat: tip ๊ด€๋ จ query ์ถ”๊ฐ€ #53 * โ™ป๏ธ refactor: api ํ˜ธ์ถœ ๋ฐฉ์‹ ์ˆ˜์ • #53 * โœจ feat: policy api ์ถ”๊ฐ€ #53 * โœจ feat: policy query ์ถ”๊ฐ€ #53 * โœจ feat: title ์†์„ฑ ์ˆ˜์ • #53 * ๐Ÿ’ฌ comment: ์ฃผ์„ ์ˆ˜์ • #53 * Feat/#52 ๋žœ๋”ฉํŽ˜์ด์ง€, ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ชจ๋‹ฌ์ฐฝ UI (#57) * ๐Ÿ› bug: DOM ๊ฒฝ๊ณ ์ฐฝ ํ•ด๊ฒฐ #52 * ๐Ÿ’„ UI: ๋กœ๊ณ  ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ #52 * ๐Ÿ’„ UI: ์บ๋ฆญํ„ฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #52 * ๐Ÿ› bug: DOM ๊ฒฝ๊ณ ์ฐฝ ํ•ด๊ฒฐ #52 * ๐Ÿ’„ UI: ํ”„๋กœํ•„ ๋ชจ๋‹ฌ ๊ด€๋ จ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #52 * โœจ feat: ํ”„๋กœํ•„ ๋ชจ๋‹ฌ ๊ตฌํ˜„ #52 * โœจ feat: ๋žœ๋”ฉํŽ˜์ด์ง€ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธํ™” #52 * ๐Ÿ’„ UI: ๋žœ๋”ฉํŽ˜์ด์ง€ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜ #52 * ๐Ÿ’„ UI: dot ๋””์ž์ธ ์ˆ˜์ • #52 * Feat/#44 UI save tip detail page (#58) * โœจ feat: SaveTipDetail ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ๊ตฌํ˜„ #44 * โ™ป๏ธ refactor: PostDetail ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #44 * โ™ป๏ธ refactor: CommentView ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #44 * โœ๏ธ Typo: props ์ค‘๋ณต ์‚ญ์ œ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ์ž…๋ ฅ์ฐฝ ๊ตฌํ˜„ #44 * โœจ feat: ๋Œ“๊ธ€ ์ž…๋ ฅ ๊ธฐ๋Šฅ ๋ฐ ๋”๋ณด๊ธฐ ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€๋ชฉ๋ก gap ์ˆ˜์ • #44 * ๐Ÿ”ง config: .gitignore์— .env ์ถ”๊ฐ€ #44 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ฐ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹ ์ˆ˜์ • #44 * โœ๏ธ Typo: ๋Œ“๊ธ€์— ... ์‚ญ์ œ #44 * โœ๏ธ Typo: ๋‹จ์–ด ์ˆ˜์ • #44 * โœ๏ธ Typo: ์˜คํƒ€ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ๊ธฐ์กด ๋Œ“๊ธ€ ์‚ญ์ œ #44 * ๐Ÿ’„ UI: ์ข‹์•„์š”, ์ €์žฅํ•˜๊ธฐ, ๊ณต์œ ํ•˜๊ธฐ ๋ฒ„ํŠผ ์ƒ์„ฑ ๋ฐ useState ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: PAGE_SIZE 5๊ฐœ๋กœ ์ˆ˜์ • #44 * ๐Ÿ’„ UI: SkeletonComment ๋Œ“๊ธ€ UI ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ๋ฌดํ•œ์Šคํฌ๋กค ๊ตฌํ˜„ #44 * ๐Ÿ“ฆ package: ๋Œ“๊ธ€ ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ˆ˜์ • #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ๋ฌดํ•œ์Šคํฌ๋กค 3๊ฐœ์”ฉ ๋กœ๋”ฉ #44 --------- Co-authored-by: rael * Fix/#59 fix search page modify (#61) * ๐Ÿ”จ fix: react Hook Rendering ์ˆœ์„œ ๋ณ€๊ฒฝ #59 * ๐Ÿ”จ fix: title Default ๊ฐ’ ์ œ๊ฑฐ ๋ฐ undefined ๋ฐฉ์ง€ #59 * Feat/#62 feat token zustand (#63) * โœจ feat: zustand ์ „์—ญ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ†ตํ•œ refresh Token ๊ตฌํ˜„ #62 * โœจ feat: hashtags 2์ค‘ ๋ฐฐ์—ด๋กœ post #62 * ๐Ÿ’„ UI: TipSection Animation ์ถ”๊ฐ€ #62 * ๐Ÿ’„ UI: height ๋ณ€๋™ #62 * โœจ feat: RoutePaths ์‚ฌ์šฉ #62 * โœจ feat: handleEmailLogin #49 * โœจ feat: ํ”„๋กœํ•„ ๋“œ๋ž๋‹ค์šด ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋กœ๊ทธ์•„์›ƒ ์ถ”๊ฐ€ #49 * โœจ feat: ๋กœ๊ทธ์ธ ์‹œ ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ”„๋กœํ•„๋กœ ๋ณ€๊ฒฝ #49 * โœจ feat: ์ „์—ญ์ƒํƒœ๊ด€๋ฆฌ๋กœ ๋กœ๊ทธ์ธ ์ƒํƒœ ๊ด€๋ฆฌ #49 * โœจ feat: ์ด๋ฉ”์ผ ๋กœ๊ทธ์ธ API ์—ฐ๊ฒฐ #49 * โœจ feat: User ์ •๋ณด ์—ฐ๊ฒฐ #49 * ๐Ÿ› bug: ์ค‘๋ณต ํŒŒ์ผ ์‚ญ์ œ์ œ * Feat/#64 feat main page modify (#68) * ๐Ÿ’„ UI: NavigationBar z-index ์ˆ˜์ • #64 * ๐Ÿ’ฌ comment: refresh ํ† ํฐ ์„ฑ๊ณต ํ™•์ธํ›„ ํ† ํฐ ์ฝ˜์†” ์ฃผ์„ํ™” #64 * ๐Ÿ’„ UI: DummyData id ์ถ”๊ฐ€ #64 * โœจ feat: Banner Animation ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #64 * โœจ feat: NavigationBar ๊ฐœ๋ฐœ์ž๋ชจ๋“œ์—์„œ ๋ฆฌ๋žœ๋”๋ง ๋ฌธ์ œ ์ž„์‹œ ํ•ด๊ฒฐ #64 * โœจ feat: Quiz Hook ๊ตฌํ˜„ #64 * โœจ feat: Search Hook ๊ตฌํ˜„ #64 * โœจ feat: TipSection Api ์—ฐ๋™ ๋ฐ ์ปดํฌ๋„ŒํŠธ ์žฌํ™œ์šฉ ํšจ์œจ ํ–ฅ์ƒ #64 * โ™ป๏ธ refactor: hashtags ์ด์ค‘ ๋ฐฐ์—ด์—์„œ ๊ทธ๋ƒฅ ๋ฐฐ์—ด๋กœ post #64 * โœจ feat: SearchPage Search Hook ์‚ฌ์šฉ ๋ฐ TipItem ํƒ€์ž… transform ์„ค์ • #64 * ๐Ÿ’„ UI: Categories UI ์  ์š”์†Œ ์žฌ๊ตฌ์„ฑ #64 * โœจ feat: Quiz API ์—ฐ๊ฒฐ ๋ฐ ํ™”๋ฉด ๊ตฌ์„ฑ #64 * โœจ feat: quizAnswer Hook ๊ตฌํ˜„ #64 * โœจ feat: QuizAnswer Hook ๊ตฌํ˜„ 2 #64 * โœจ feat: QuizAnswer Api ์—ฐ๊ฒฐ #64 * โ™ป๏ธ refactor: ํฐ ํ™”๋ฉด์—์„œ ๋ฐฐ๋„ˆ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ€๋กœ ์Šคํฌ๋กค ๋ฐœ์ƒ ๋ฌธ์ œ ํ•ด๊ฒฐ #64 * ๐Ÿ’ฌ comment: Quiz Skeleton UI ๊ตฌํ˜„์ „ ์ฃผ์„์ฒ˜๋ฆฌ #64 * โ™ป๏ธ refactor: axios-instance ์ž์ฒด์— ๊ถŒํ•œ ์ˆ˜์—ฌ #64 * ๐Ÿ”จ fix: ์ •๋‹ต์ผ ๋•Œ๋งŒ server๋กœ post #64 * โ™ป๏ธ refactor: quizAPI ํŒŒ์ผ ์ด๋ฆ„ ์ •๋ฆฌ ๋ฐ api ํ†ตํ•ฉ #64 * โ™ป๏ธ refactor: ์ˆ˜์ •๋œ hook ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ #64 * Feat/#73 feat create page modify (#74) * โœจ feat: ๊ธ€ ์ƒ์„ฑ์‹œ userID ์ถ”๊ฐ€ #73 * โœจ feat: TipCreate Api ๋ถ„๋ฆฌ #73 * โœจ feat: SearchModal Close์‹œ ์ž…๋ ฅ์ฐฝ ์ดˆ๊ธฐํ™” #73 * Feat/#75 UI challenge page UI (#77) * โœจ feat: ๊ธ€ ์ƒ์„ฑ์‹œ userID ์ถ”๊ฐ€ #73 * โœจ feat: TipCreate Api ๋ถ„๋ฆฌ #73 * โœจ feat: SearchModal Close์‹œ ์ž…๋ ฅ์ฐฝ ์ดˆ๊ธฐํ™” #73 * โœจ feat: FetchUser ํ›„ user.nickname ๋ถˆ๋Ÿฌ์˜ค๊ธฐ #75 * ๐Ÿ’„ UI: ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #75 * ๐Ÿ’„ UI: Card border-radius ์ˆ˜์ • #75 * โœจ feat: RoutePath์— Challenge ์ถ”๊ฐ€ #75 * โœจ feat: NumberCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: Challenge Banner ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: ChallengeHeader ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: Challenge TipSection ๊ตฌํ˜„ ๋ฐ InfiniteScroll / Skeleton UI ์ ์šฉ #75 * ๐Ÿ’„ UI: ChallengePage UI #75 * Feat/#79 feat image upload & ErrorPage & SearchTag (#80) * โœจ feat: Image Post ์ถ”๊ฐ€ #79 * โœจ feat: ErrorPage ๊ตฌํ˜„ ๋ฐ ์—ฐ๊ฒฐ #79 * โ™ป๏ธ refactor: SearchPage ์—๋Ÿฌ ๋ฐœ์ƒ ์ฝ”๋“œ ์ž„์‹œ ์กฐ์น˜ ์ถ”ํ›„ ์ˆ˜์ • ์˜ˆ์ • #79 * โœจ feat: Search Tag ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #79 * โœจ feat: Image Upload์‹œ ์—ฌ๋Ÿฌ ๋ฒˆ ์—…๋กœ๋“œ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ #79 * โ™ป๏ธ refactor: API interface Type ์„ค์ • #79 * Feat/#60 UI chatbot (#81) * โœจ feat: ์ฑ—๋ด‡ ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ „์†ก ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ๊ฒ€์ƒ‰๋ฐ” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ํŽ˜์ด์ง€ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์˜ค๋ฅธ์ชฝ ํ™”์‚ดํ‘œ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์‚ฌ์ด๋“œ๋ฐ” ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€ #60 * ๐Ÿ’ฌ comment: ์ฑ—๋ด‡ ์ฃผ์„ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: add chatbot icon #60 * โœจ feat: ์ฑ„ํŒ…๋ฐฉ ์ €์žฅ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #60 * โœจ feat: ์—”ํ„ฐ ํด๋ฆญ์‹œ ์ „์†ก ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #60 * โœจ feat: ๋ฒ„ํŠผ ์—ฐ๊ฒฐ #60 * โœจ feat: ์ฑ„ํŒ… api ์—ฐ๊ฒฐ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜ #60 * โœจ feat: ๋ฒ„ํŠผ๋ณ„ ์งˆ๋ฌธ ํ…์ŠคํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ› bug: ์ฒซํด๋ฆญ ์ฑ„ํŒ… ์•ˆ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #60 * ๐Ÿ”จ fix: ๋ผ์šฐํŠธ ๋จธ์ง€ ํ•ด๊ฒฐ #60 * Feat/#85 feat main page filter & chatbot Icon (#87) * ๐Ÿ’„ UI: ChatBot Icon ์ถ”๊ฐ€ #85 * โœจ feat: ๋‚ ์งœ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #85 * ๐Ÿ”ฅ remove: RecommedTipSection ์‚ญ์ œ #85 * โ™ป๏ธ refactor: SearchApi Tag๋กœ๋งŒ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ query ์˜ต์…”๋„ ์ถ”๊ฐ€ #85 * โœจ feat: user HashTag Get, Post #85 * โ™ป๏ธ refactor: TipSection ์žฌํ™œ์šฉ์„ฑ ๊ทน๋Œ€ํ™” / useTipList, useSearchList ์กฐ๊ฑด๋ฌธ์„ ํ†ตํ•ด ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ / Card ์™€ BigCard ์กฐ๊ฑด๋ฌธ์œผ๋กœ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ #85 * ๐Ÿ’„ UI: ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ title ๋ฌธ๊ตฌ ์ˆ˜์ • ๋ฐ ๋ฐ์ดํ„ฐ ์ˆ˜์ • #85 * โ™ป๏ธ refactor: useSearchList Sorted ์˜ต์…˜ ์ถ”๊ฐ€ #85 * โ™ป๏ธ refactor: defaultSort Props ์ถ”๊ฐ€ #85 * ๐Ÿ’„ UI: ์นดํ…Œ๊ณ ๋ฆฌ visible default ์ˆ˜์ • #85 * โœ๏ธ typo: bookmarks -> saves #85 * ๐Ÿ”ฅ remove: console.log ์ œ๊ฑฐ #85 * โ™ป๏ธ refactor: query ์ถ”๊ฐ€ ๋ฐ isMoreLimit ์กฐ๊ฑด ์ถ”๊ฐ€ #85 * ๐Ÿ”ฅ remove: console ์ œ๊ฑฐ #85 * Feat/#84 UI my challenge (#88) * โœจ feat: MyChallenge Path ์ถ”๊ฐ€ #84 * ๐Ÿ”จ fix: navigate ์ฃผ์†Œ ์ˆ˜์ • #84 * ๐Ÿ’„ UI: MyChallenge UI ๊ตฌํ˜„ #84 * ๐Ÿ’„ UI: Challenge Tip Skeleton ์ถ”๊ฐ€ #84 * ๐Ÿ’„ UI: cursor: pointer ์ถ”๊ฐ€ ์™„๋ฃŒ #84 * Feat/#90 UI challenge detail page (#91) * ๐Ÿ”ง config: ์ฑŒ๋ฆฐ์ € ์ƒ์„ธ ํŽ˜์ด์ง€ ๋ผ์šฐํ„ฐ ์—ฐ๊ฒฐ #90 * โœจ feat: onCardClick ์†์„ฑ ์ถ”๊ฐ€ #90 * โœจ feat: onCardClick ํ•จ์ˆ˜ ์ถ”๊ฐ€ [#90] * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ #90 * โœจ feat: ChallengeDetailPage ์ถ”๊ฐ€ #90 * โœจ feat: ChallengeDetail ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #90 * โœจ feat: ChallengeComment ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #90 * โ™ป๏ธ refactor: FloatingToggleBtn ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #90 * ๐Ÿ’„ UI: ์ฑŒ๋ฆฐ์ง€ ์ƒ์„ธ ํŽ˜์ด์ง€ UI ๊ตฌํ˜„ #90 * ๐Ÿ’„ UI: ์ฑŒ๋ฆฐ์ง€ ์ƒ์„ธ ํŽ˜์ด์ง€ ์ฐธ๊ฐ€์ž ํ›„๊ธฐ UI ๊ตฌํ˜„ #90 * โœจ feat: handleCardClick ์ถ”๊ฐ€ [#90] * Feat/#76 feature page api (#92) * ๐Ÿ’„ UI: ๋งˆ์ดํŽ˜์ด์ง€ UI ์ˆ˜์ • #76 * โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ (์ด๋ฏธ์ง€ ์ˆ˜์ • api ํ•„์š”) #76 * โœจ feat: ์ตœ๊ทผ ๋ณธ ๊ฟ€ํŒ ๊ธฐ๋Šฅ (์ €์žฅ๋œ ๊ฟ€ํŒ ํŽ˜์ด์ง€๊นŒ์ง€๋งŒ ์ถ”๊ฐ€๋จ/๋ฉ”์ธ, ๋งค๊ฑฐ์ง„ ๋“ฑ๋“ฑ handleCardClick ์ถ”๊ฐ€์ˆ˜์ • ํ•ด์•ผํ•จ.) #76 * โœจ feat: ๋ฌดํ•œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ํ•ด๊ฒฐ #76 * ๐Ÿ“ฆ package: InfiniteQuery ์ถ”๊ฐ€ #76 * โœจ feat: getSavedTips api ์ถ”๊ฐ€ (์•„์ง ์—๋Ÿฌ ํ•ด๊ฒฐX) #76 * โœจ feat: useSaveTipList ์ฟผ๋ฆฌ ์ด์šฉํ•ด์„œ ๋ฌดํ•œ์Šคํฌ๋กค ์ถ”๊ฐ€ ์‹œ๋„ #76 * โœจ feat: api ์—ฐ๊ฒฐ ์ค‘ #76 * โœจ feat: tip ํ˜•์‹ ํ†ต์ผ #76 * โœจ feat: ์นด์นด์˜ค ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #76 * โœจ feat: getTipDetail api, useTipDetail ์ถ”๊ฐ€ #76 * โœจ feat: dummydata ์‚ญ์ œ ํ›„ api ์—ฐ๊ฒฐ ์‹œ๋„ #76 * โœจ feat: comment get, post, put, delete api ์ถ”๊ฐ€ #76 * โœจ feat: ์ข‹์•„์š”์™€ ๋ถ๋งˆํฌ ํ† ๊ธ€ api ์ถ”๊ฐ€ #76 * โœจ feat: ์ข‹์•„์š”์™€ ๋ถ๋งˆํฌ mutation ์ถ”๊ฐ€ #76 * ๐Ÿ’„ UI: ํ† ๊ธ€ ๋ฒ„ํŠผ๋“ค ์ปดํฌ๋„ŒํŠธํ™” #76 * โ™ป๏ธ refactor: ์ปดํฌ๋„ŒํŠธํ™” ๋ฐ˜์˜ #76 * ๐Ÿ’„ UI: ๊ฟ€ํŒ ์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #76 * โ™ป๏ธ refactor: ์ €์žฅ ์œ„์น˜ ๋ณ€๊ฒฝ #76 * โœจ feat: ์ €์žฅ ๊ฟ€ํŒ ๋ฐ˜ํ™˜๊ฐ’ ์ˆ˜์ • #76 * ๐Ÿ’„ UI: modify width #76 * ๐Ÿ’„ UI: remove text #76 * โœจ feat: ์ €์žฅํ•œ ๊ฟ€ํŒ api ์—ฐ๊ฒฐ #76 * โœจ feat: ์นด์นด์˜ค ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์˜ค๋ฅ˜ ์ˆ˜์ • [#76] * ๐Ÿ’„ UI: cursor pointer ์ถ”๊ฐ€ [#76] * โœจ feat: ์ด๋ฉ”์ผ ์ž…๋ ฅ ํผ api ์ˆ˜์ • #76 * โœจ feat: ์ข‹์•„์š” ๋ฐ ์ €์žฅ ์—ฌ๋ถ€ ์ €์žฅ #76 * ๐Ÿ’ฌ comment: ์ฃผ์„ ์‚ญ์ œ #76 * โ™ป๏ธ refactor: DTO ์ˆ˜์ •์‚ฌํ•ญํ•ญ ๋ฐ˜์˜ #76 * โœจ feat: ๋Œ“๊ธ€ api ์—ฐ๊ฒฐ #76 * โœจ feat: ๋Œ“๊ธ€ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #76 * ๐Ÿ› bug: ์นด์นด์˜ค ๊ณต์œ  #76 * โœจ feat: ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ ๋ฐ˜์˜ #76 * ๐Ÿ› bug: ํƒ€์ž… ์—๋Ÿฌ ํ•ด๊ฒฐ #76 * โ™ป๏ธ refactor: ๋Œ“๊ธ€ ์ธํ„ฐํŽ˜์ด์Šค ์ ์šฉ #76 * โœจ feat: ํšŒ์›๊ฐ€์ž… api ์—ฐ๊ฒฐ #76 * โœจ feat: userStore updateProfile ์ถ”๊ฐ€ #76 * โœจ feat: ์˜ค๋ฅ˜ ์ˆ˜์ • #76 * ๋ณต์ œ ๋ฌธ์„œ ์‚ญ์ œ * โœจ feat: ํšŒ์›๊ฐ€์ž… ์˜ค๋ฅ˜ ์ˆ˜์ •์ค‘ #76 --------- Co-authored-by: rael Co-authored-by: Head-ddy <80982532+Head-ddy@users.noreply.github.com> * Feat/#89 Navigation bar UI (#93) * ๐Ÿ’„ UI: ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ˜ธ๋ฒ„๋ง ์ถ”๊ฐ€ #89 * โœจ feat: ํŒŒ๋น„์ฝ˜ ์ถ”๊ฐ€ #89 * ๐Ÿ› bug: ์ถฉ๋Œ ์—๋Ÿฌ ํ•ด๊ฒฐ * Feat/#82 api magazine (#94) * ๐Ÿ’„ UI: ๋งค๊ฑฐ์ง„ ์บ๋ฆญํ„ฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #82 * โœจ feat: ์ธ๊ธฐ ํ•ด์‹œํ…Œ๊ทธ ์—ฐ๊ฒฐ #82 * โœจ feat: ๋งค๊ฑฐ์ง„ ์ƒ์„ธ ์ •๋ณด api ์—ฐ๊ฒฐ #82 * โœจ feat: ์ „์ฒด ์ด๋ฏธ์ง€๋ณด๊ธฐ ๋ชจ๋‹ฌ ์ถ”๊ฐ€ #82 * ๐Ÿ› bug: ์ •์ฑ… api ์ธํ„ฐํŽ˜์ด์Šค ์ˆ˜์ • #82 * ๐Ÿ› bug: ํƒ€์ž… ์—๋Ÿฌ๋Ÿฌ * Fix/#96 fix landing page access (#98) * โœจ feat: AuthWrapper ํ†ตํ•ด ๊ถŒํ•œ ์—†์ด ๋‹ค๋ฅธ ํŽ˜์ด์ง€ ์ ‘๊ทผ ์ œํ•œ #96 * โ™ป๏ธ refactor: ์‹ค์ œ accessToken ์œผ๋กœ ์ ‘๊ทผ #96 * โ™ป๏ธ refactor: refreshToken Default ๊ฐ’ null ์„ค์ • #96 * Feat/#66 fix signup modify (#99) * ๐Ÿ”ง config: gitignore ์ˆ˜์ • #66 * โœจ feat: ์ „์ฒด ์ด์šฉ์•ฝ๊ด€ ์ฒดํฌ๋ฐ•์Šค ์˜ค๋ฅ˜ ์ˆ˜์ • #66 * โœ๏ธ Typo: ํ•„์š”์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ #66 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ๋‹‰๋„ค์ž„ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ๋‹‰๋„ค์ž„ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ #66 * ๐Ÿ’„ UI: ํšŒ์›๊ฐ€์ž… ๋‹จ๊ณ„ UI ์ˆ˜์ • #66 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต! #66 * โœจ feat: ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ ๋ฐ ๋ฒ„ํŠผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ #66 * โœจ feat: api ์ˆ˜์ • #66 * โœจ feat: ํšŒ์›๊ฐ€์ž… ํ›„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ #66 * โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ #66 * โœจ feat: ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ ์ˆ˜์ • #66 * ๐Ÿ’„ UI: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต alert ์ถ”๊ฐ€ #66 * Fix/#97/saved tips (#100) * โœจ feat: ์ƒ๋‹จ ์Šคํฌ๋กค ๊ธฐ๋Šฅ #97 * โœจ feat: ๋กœ๊ณ  ์ด๋ฏธ์ง€์—๋„ ์ƒ๋‹จ ์Šคํฌ๋กค ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #97 * ๐Ÿ’„ UI: ํฌ์ธํ„ฐ ์ถ”๊ฐ€ #97 * โœจ feat: ์ข‹์•„์š” & ์ €์žฅ ์ˆ˜ ์ถ”๊ฐ€ #97 * โœจ feat: ์‚ฌ์ง„ ๊ฐœ์ˆ˜์— ๋”ฐ๋ฅธ ๊ทธ๋ฆฌ๋“œ ์ถ”๊ฐ€ #97 * โœจ feat: ์‚ฌ์ง„ 5๊ฐœ ์ž„์‹œ ๊ทธ๋ฆฌ๋“œ #97 * โœจ feat: profile image ์ถ”๊ฐ€ #97 * Feat/#69 feature kakao login (#102) * โœจ feat: ์นด์นด๋กœ ๋กœ๊ทธ์ธ ์—”๋“œํฌ์ธํŠธ ์ˆ˜์ • #69 * โœจ feat: ์นด์นด์˜ค ๋กœ๊ทธ์ธ #69 * โœจ feat: ํ•ธ๋“ค ์นด์นด์˜ค ๋กœ๊ทธ์ธ #69 * ๐Ÿ› bug: ์ถฉ๋Œ ์—๋Ÿฌ๋Ÿฌ #69 * โœจ feat: ํ•ธ๋“ค ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ˆ˜์ • #69 * โœจ feat: ํ•ธ๋“ค ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ˆ˜์ •์ค‘... #69 * ๐Ÿ› bug: ์นด์นด์˜ค ๋กœ๊ทธ์ธ ํ•ด๊ฒฐ #69 --------- Co-authored-by: rael --------- Co-authored-by: S-Gihun <89789115+S-Gihun@users.noreply.github.com> Co-authored-by: rael Co-authored-by: Head-ddy <80982532+Head-ddy@users.noreply.github.com> Co-authored-by: Rael --- umc-master/index.html | 2 +- umc-master/src/pages/auth/KakaoCallback.tsx | 70 ++++++++----------- .../pages/auth/Login_components/InputForm.tsx | 54 +++++++++++--- 3 files changed, 73 insertions(+), 53 deletions(-) diff --git a/umc-master/index.html b/umc-master/index.html index e76b095..14b710e 100644 --- a/umc-master/index.html +++ b/umc-master/index.html @@ -11,7 +11,7 @@ /> ํ™ˆ๋งˆ์Šคํ„ฐ - +
diff --git a/umc-master/src/pages/auth/KakaoCallback.tsx b/umc-master/src/pages/auth/KakaoCallback.tsx index ff9e035..918e89d 100644 --- a/umc-master/src/pages/auth/KakaoCallback.tsx +++ b/umc-master/src/pages/auth/KakaoCallback.tsx @@ -1,54 +1,42 @@ import React, { useEffect } from 'react'; -import axios from 'axios'; import { useNavigate } from 'react-router-dom'; +import axiosInstance from '@apis/axios-instance'; +import { useTokenStore } from '@store/tokenStore'; +import { useAuthStore } from '@store/authStore'; const KakaoCallback: React.FC = () => { - + const { setAuth } = useAuthStore(); + const { setTokens } = useTokenStore(); const navigate = useNavigate(); useEffect(() => { - const getAccessToken = async () => { - const queryParams = new URLSearchParams(window.location.search); - const code = queryParams.get('code'); - - if (!code) { - console.error('Authorization code not found'); - return; - } - - try { - // ์นด์นด์˜ค์—์„œ Access Token ์š”์ฒญ - const response = await axios.post('https://kauth.kakao.com/oauth/token', { - grant_type: 'authorization_code', - client_id: import.meta.env.VITE_KAKAO_API_KEY, - redirect_uri: 'http://localhost:3000/oauth/kakao/callback', - code, - }); - - const kakaoAccessToken = response.data.access_token; - - // ๋ฐฑ์—”๋“œ๋กœ ์นด์นด์˜ค Access Token ์ „์†ก - const backendResponse = await axios.post('http://localhost:3000/login/kakao', { - kakaoAccessToken, + const urlParams = new URLSearchParams(window.location.search); + const code = urlParams.get('code'); + + if (code) { + console.log('โœ… ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ฝ”๋“œ ํ™•์ธ:', code); + + axiosInstance + .post('/login/kakao', { code }) + .then((response) => { + const { accessToken, refreshToken } = response.data.result; + setTokens({ accessToken, refreshToken }); + localStorage.setItem('accessToken', accessToken); + localStorage.setItem('refreshToken', refreshToken); + setAuth(true); + navigate('/main'); + }) + .catch(() => { + // console.error('โŒ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹คํŒจ:', error.response?.data || error.message); + // alert(error.response?.data?.message || '์นด์นด์˜ค ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'); + navigate('/'); }); - - const { accessToken, refreshToken } = backendResponse.data.result; - - // Access Token ๋ฐ Refresh Token ์ €์žฅ (์˜ˆ: ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€) - localStorage.setItem('accessToken', accessToken); - localStorage.setItem('refreshToken', refreshToken); - - // ํ™ˆ ๋˜๋Š” ์‚ฌ์šฉ์ž ๋Œ€์‹œ๋ณด๋“œ๋กœ ์ด๋™ - navigate('/'); - } catch (error) { - console.error('Failed to login with Kakao:', error); - } - }; - - getAccessToken(); + } else { + console.warn('โš ๏ธ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ฝ”๋“œ ์—†์Œ'); + } }, [navigate]); - return
์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ค‘โ€ฆ
; + return <>; }; export default KakaoCallback; diff --git a/umc-master/src/pages/auth/Login_components/InputForm.tsx b/umc-master/src/pages/auth/Login_components/InputForm.tsx index 2204ddb..5fafebb 100644 --- a/umc-master/src/pages/auth/Login_components/InputForm.tsx +++ b/umc-master/src/pages/auth/Login_components/InputForm.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components'; import Input from '@components/Input/Input'; import useInput from '@hooks/useInput'; import { validateEmailFormat, validatePasswordFormat } from '@utils/validation'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import Button from '@components/Button/Button'; import Kakao_Image from '@assets/kakao_login/kakao_login_large_wide.png'; import { useNavigate } from 'react-router-dom'; @@ -12,14 +12,49 @@ import axiosInstance from '@apis/axios-instance'; import { useAuthStore } from '@store/authStore'; import { useTokenStore } from '@store/tokenStore'; +const KAKAO_REDIRECT_URI = + import.meta.env.MODE === 'development' + ? 'http://localhost:5173/oauth/kakao/callback' + : 'https://www.hmaster.shop/oauth/kakao/callback'; + const InputForm: React.FC = () => { const { setAuth } = useAuthStore(); - const { setTokens } = useTokenStore.getState(); + const { setTokens } = useTokenStore(); + const navigate = useNavigate(); + + useEffect(() => { + if (!window.Kakao) { + console.warn('โš ๏ธ window.Kakao๊ฐ€ ์—†์Œ, SDK ๋กœ๋“œ ์‹œ์ž‘'); + + const script = document.createElement('script'); + script.src = 'https://developers.kakao.com/sdk/js/kakao.js'; + script.async = true; + script.onload = () => { + console.log('โœ… ์นด์นด์˜ค SDK ๋กœ๋“œ ์™„๋ฃŒ:', window.Kakao); + if (window.Kakao && !window.Kakao.isInitialized()) { + console.error('โŒ window.Kakao๋Š” ์žˆ์ง€๋งŒ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์Œ! init() ํ•„์š”'); + window.Kakao.init(import.meta.env.VITE_JAVASCRIPT_KEY); + console.log('โœ… ์นด์นด์˜ค SDK ๊ฐ•์ œ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ'); + } + }; + document.head.appendChild(script); + } else { + console.log('โœ… window.Kakao ์ด๋ฏธ ๋กœ๋“œ๋จ'); + if (!window.Kakao.isInitialized()) { + console.error('โŒ window.Kakao๋Š” ์žˆ์ง€๋งŒ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์Œ! init() ํ•„์š”'); + window.Kakao.init(import.meta.env.VITE_JAVASCRIPT_KEY); + console.log('โœ… ์นด์นด์˜ค SDK ๊ฐ•์ œ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ'); + } + } + }, []); const handleKakaoLogin = () => { - const KAKAO_API_KEY = import.meta.env.VITE_KAKAO_API_KEY; - const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${KAKAO_API_KEY}&redirect_uri=http://localhost:3000/oauth/kakao/callback&response_type=code`; - window.location.href = kakaoAuthUrl; + const clientId = import.meta.env.VITE_JAVASCRIPT_KEY; + const redirectUri = encodeURIComponent(KAKAO_REDIRECT_URI); + const fallbackUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code`; + + console.log('โœ… fallback URL๋กœ ๋ฆฌ๋””๋ ‰์…˜:', fallbackUrl); + window.location.href = fallbackUrl; }; const handleEmailLogin = async () => { @@ -72,13 +107,12 @@ const InputForm: React.FC = () => { e.preventDefault(); setIsSubmitted(true); - // ์ด๋ฉ”์ผ ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋น„์–ด์žˆ๋Š”์ง€ ์ฒดํฌํ•˜๊ณ  ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ if (!email) { handleEmailError('์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); } else { const emailError = validateEmailFormat(email); if (emailError) { - handleEmailError(emailError); // ์ด๋ฉ”์ผ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ + handleEmailError(emailError); } } @@ -87,7 +121,7 @@ const InputForm: React.FC = () => { } else { const passwordError = validatePasswordFormat(password); if (passwordError) { - handlePasswordError(passwordError); // ๋น„๋ฐ€๋ฒˆํ˜ธ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ + handlePasswordError(passwordError); } } @@ -110,8 +144,6 @@ const InputForm: React.FC = () => { await handleEmailLogin(); }; - const navigate = useNavigate(); // ์ถ”๊ฐ€ - return ( @@ -132,7 +164,7 @@ const InputForm: React.FC = () => { - From a11140f5676efda3135f63dc74fd08c759d18d07 Mon Sep 17 00:00:00 2001 From: Minji Kim Date: Fri, 21 Feb 2025 11:13:25 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=9A=91=20hotfix:=20=EC=9D=B8=ED=94=8C?= =?UTF-8?q?=EB=A3=A8=EC=96=B8=EC=84=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- umc-master/src/pages/magazine/MagazinePage.tsx | 3 +-- umc-master/src/pages/magazine/components/cardGrid.tsx | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/umc-master/src/pages/magazine/MagazinePage.tsx b/umc-master/src/pages/magazine/MagazinePage.tsx index 3f4983b..d25c226 100644 --- a/umc-master/src/pages/magazine/MagazinePage.tsx +++ b/umc-master/src/pages/magazine/MagazinePage.tsx @@ -5,13 +5,12 @@ import styled from 'styled-components'; import Typography from '@components/common/typography'; import MindMap from './components/mindMap'; import CardGrid, { CardGridData } from './components/cardGrid'; -import dummyImg from '@assets/dummyImage/dummy.jpeg'; import { usePolicies } from '@apis/queries/usePolicyQueries'; const generateDummyData = (): CardGridData[] => { return Array.from({ length: 9 }, (_, index) => ({ id: String(index + 1), - image: dummyImg, + image: 'https://i.pinimg.com/736x/af/a0/76/afa07695334ef42a7864f09a0099a679.jpg', text: `๋”๋ฏธ ๋ฐ์ดํ„ฐ ${index + 1}`, likes: Math.floor(Math.random() * 2000) + 1000, bookmarks: Math.floor(Math.random() * 2000) + 1000, diff --git a/umc-master/src/pages/magazine/components/cardGrid.tsx b/umc-master/src/pages/magazine/components/cardGrid.tsx index 18c53e9..de19350 100644 --- a/umc-master/src/pages/magazine/components/cardGrid.tsx +++ b/umc-master/src/pages/magazine/components/cardGrid.tsx @@ -2,7 +2,6 @@ import React from 'react'; import styled from 'styled-components'; import { useNavigate } from 'react-router-dom'; import CardInfo from '@components/Card/CardInfo'; -import dummyImg from '@assets/dummyImage/dummy.jpeg'; export interface PolicyData { id: number; @@ -34,7 +33,7 @@ const transformPolicies = (policies: PolicyData[] | undefined): CardGridData[] = if (!policies) return []; return policies.map((policy) => ({ id: policy.id.toString(), - image: policy.imageUrl || dummyImg, // ์ด๋ฏธ์ง€ ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’ + image: policy.imageUrl || 'https://i.pinimg.com/736x/af/a0/76/afa07695334ef42a7864f09a0099a679.jpg', // ์ด๋ฏธ์ง€ ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’ text: policy.title, likes: policy.likeCount ?? 0, // undefined ๋ฐฉ์ง€ bookmarks: policy.bookmarkCount ?? 0, // undefined ๋ฐฉ์ง€ From 4bf6154e54a92897f8f66047e12e4efa542f332c Mon Sep 17 00:00:00 2001 From: S-Gihun <89789115+S-Gihun@users.noreply.github.com> Date: Fri, 21 Feb 2025 13:48:17 +0900 Subject: [PATCH 4/5] develop (#106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * โœจ feat: MainPage Banner UI ๊ตฌํ˜„ * ๐Ÿ’„ UI: Banner padding ์ˆ˜์ • # 11 * โœจ feat: QuizBox ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * โœจ feat: SearchBar ๊ตฌํ˜„ #11 * โœจ feat: Categories ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * ๐Ÿ”ง config: Font Awesome ์„ค์น˜ #11 * ๐Ÿ’„ UI: categories ์•„๋ž˜ ํ™”์‚ดํ‘œ ์ถ”๊ฐ€ #11 * โœจ feat : TipsSection ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #11 * โœจ feat: LoginPage Title&Input UI ๊ตฌํ˜„ #10 * โœจ feat: LoginPage LoginOptions UI ๊ตฌํ˜„ #10 * โœจ feat: LoginPage LoginButton UI ๊ตฌํ˜„ #10 * โ™ป๏ธ refactor: LoginPage Title component #10 * โ™ป๏ธ refactor: LoginPage Title component #10 * โ™ป๏ธ refactor: LoginPage ButtonBox component #10 * โ™ป๏ธ refactor: LoginPage InputForm component #10 * ๐Ÿ’„ UI : TipsSectionTopFive ์ค‘๋ณต ์‚ญ์ œ #11 * ๐Ÿ’„ UI : Card Component ๋ถ„๋ฆฌ ์ž‘์—… #11 * ๐Ÿ’„ UI : SearchBar/ Card ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #11 * ๐Ÿ”ง config: CI ๊ฒฝ๋กœ ์ˆ˜์ • #7 * ๐Ÿ”ง config: cwd ์ถ”๊ฐ€ #7 * ๐Ÿ”ง config: ๋ผ์šฐํŒ… ๋™์ž‘ ์œ„ํ•œ ํŒŒ์ผ ์ถ”๊ฐ€ #7 * ๐Ÿ’„ UI: LoginPage KakaoLogin Button ์ˆ˜์ • #10 * ๐Ÿ’„ UI: LoginPage UI์‚ฌ์ด์ฆˆ ์ถ•์†Œ #10 * ๐Ÿ’„ UI: LoginPage UI์‚ฌ์ด์ฆˆ ํ™•๋Œ€ (Figma Size) #10 * โœจ feat: add MyPage router #16 * โœจ feat: MyPage Title&์ƒ๋‹จ์นด๋“œ ๊ตฌํ˜„ํ˜„ #16 * โœจ feat: MyPage ํ”„๋กœํ•„ ๋ณ€๊ฒฝ ๋ฒ„ํŠผ ์ถ”๊ฐ€๊ฐ€ #16 * ๐Ÿ”ง config: eslint ๊ทœ์น™ ์ œ๊ฑฐ #12 * ๐Ÿ“ฆ package: add react-icons #12 * ๐ŸŽจ styles: update reset.css file #12 * ๐Ÿ’„ UI: add logo image #12 * โœจ feat: ํ—ค๋” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #12 * โœจ feat: ํ‘ธํ„ฐ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #12 * ๐Ÿ’„ UI: ํ—ค๋” ํ‘ธํ„ฐ ๋ ˆ์ด์•„์›ƒ ์ถ”๊ฐ€ #12 * โœจ feat: MyPage ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ถ”๊ฐ€ & ์นด๋“œ ์ปดํฌ๋„ŒํŠธ #16 * โœ๏ธ typo: MyPage GoodTip->RecnetGoodTip์œผ๋กœ ์ˆ˜์ •์ • #16 * โœจ feat: MyPage Best ๊ฟ€ํŒ ์„ ์ • ํšŸ์ˆ˜ & ๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ ์ปดํฌ๋„ŒํŠธ #16 * โ™ป๏ธ refactor: MyPage ProfileSection ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage RecentTips ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage dummyData ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage BestInterest ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage ์ด์Šˆ๋ฒˆํ˜ธ ์ˆ˜์ •์ • #16 * ๐Ÿ’„ UI: MyPage ์ปดํฌ๋„ŒํŠธ ์œ„์น˜ ์ˆ˜์ • #16 * ๐Ÿ“ฆ package: add framer-motion #12 * ๐ŸŽจ style: ์„ ๋ฌผ์ƒ์ž, ํŠธ๋กœํ”ผ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #12 * โœจ feat: ์Šคํฌ๋กค ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ›… ์ถ”๊ฐ€ #12 * โœจ feat: add LandingPage #12 * ๐Ÿ’„ UI : Card CSS ์ค‘๋ณต ์ œ๊ฑฐ #19 * ๐Ÿ’„ UI : dummy Image ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI : max-width -> min-width ์ˆ˜์ • #19 * ๐Ÿ’„ UI : SearchSection ์ปดํฌ๋„ŒํŠธ ์„ธ๋ถ„ํ™” ๋ฐ CSS ์ˆ˜์ • #19 * ๐Ÿ’„ UI : TipSection Props ํ˜•์‹ ์ˆ˜์ • #19 * ๐Ÿ’„ UI : Search Bar ๊ณต์šฉ ์‚ฌ์šฉ์œผ๋กœ ์ธํ•œ CSS ์ˆ˜์ • #19 * ๐Ÿ’„ UI : ๊ณต์šฉ BigCard ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI : SearchPage ๊ตฌํ˜„ #19 * ๐Ÿ’„ UI : SearchPage Recommended Title ์ปดํฌ๋„ŒํŠธ #19 * ๐Ÿ’„ UI : SearchPage TipSection ๊ตฌํ˜„ #19 * ๐Ÿ’„ UI : dummyImage MainPage์— ์ถ”๊ฐ€ #19 * ๐Ÿ’„ UI: LoginPage Input.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ ๋ฐ Style ์ˆ˜์ • #10 * โ™ป๏ธ refactor: LoginPage Button.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #10 * ๐Ÿ’„ UI : Button ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #10 * ๐Ÿ’„ UI : Input ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #10 * โ™ป๏ธ refactor: MyPage InterestTag.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #16 * โ™ป๏ธ refactor: MyPage Section.tsx ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #16 * ๐Ÿ’„ UI : InterestTag ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ #16 * ๐Ÿ”ฅ remove: isAuth ์‚ญ์ œ #12 * โœจ feat: add font #22 * โœจ feat: add themeProvider #22 * โœจ feat: add globalStyle #22 * โœจ feat: add typography #22 * โ™ป๏ธย refactor: kakao_login ์ด๋ฏธ์ง€ ํŒŒ์ผ ์œ„์น˜ ๋ณ€๊ฒฝ #10 * โ™ป๏ธย refactor: <> ์‚ญ์ œ #10 * โœ๏ธย typo: ํด๋” ์ด๋ฆ„ ๋ณ€๊ฒฝ (MyPage_components -> components) #16 * โœ๏ธย typo: ์˜คํƒ€ ์ˆ˜์ • (ProfileCard2 -> ProfileCard) #16 * โ™ป๏ธ refactor: <> ์‚ญ์ œ #16 * โ™ป๏ธ refactor: import ๊ฒฝ๋กœ๋ฅผ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋กœ ๋ณ€๊ฒฝ #16 * โ™ป๏ธ refactor : keypress -> keydown ์œผ๋กœ ์ˆ˜์ • #19 * โ™ป๏ธ refactor : text1, text2 ์ˆซ์ž ์‚ฌ์šฉ front, backText ๋กœ ์ˆ˜์ • #19 * ๐Ÿ”ง config: package-lock ํŒŒ์ผ ์‚ญ์ œ * ๐Ÿ’„ UI: modify logo image file #25 * โœจ feat: ์ถ”๊ฐ€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜ #22 * โœจ feat: ์ถ”๊ฐ€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ํƒ€์ดํฌ ๋ฐ˜์˜ #22 * ๐Ÿ’„ UI: Title ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: LoginPage ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ“ฆ package: add vite-plugin-svgr #25 * ๐Ÿ”ง config: svg ์‚ฌ์šฉ ์œ„ํ•œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ์„ค์ • #25 * ๐Ÿ’„ UI: ์•Œ๋ฆผ ์•„์ดํ†ค ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: update Navigation Bar #25 * โœ๏ธ Typo: todo ํ…์ŠคํŠธ ์ค‘๋ณต ์‚ญ์ œ #25 * ๐Ÿ’„ UI: Input ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: Button ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„ UI: LoginPage ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #26 * ๐Ÿ’„UI: logo ์•„์ด์ฝ˜ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: ํ‘ธํ„ฐ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜ #25 * โœจ feat: SignupPage ๊ตฌ์กฐ #21 * โœจ feat: ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ๊ณ ์ • #25 * โœจ feat: ํ”„๋กœํ•„ ์•„๋ฐ”ํƒ€ ์ƒ์„ฑ #21 * โœจ feat: ํ”„๋กœํ•„ ์ถ”๊ฐ€ ๋ฒ„ํŠผ #21 * ๐Ÿ”ง config: design system ์ถ”๊ฐ€ #24 * ๐Ÿ’„ UI: Tag ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #24 * ๐Ÿ’„ UI: Card ์ปดํฌ๋„ŒํŠธ ๋””์ž์ธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Banner UI ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Search UI ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Quiz ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: TipSection ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Category ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: MainPage ์ˆ˜์ • #24 * โœจ feat: ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€ #21 * ๐ŸŽจ style: alarm ์•„์ด์ฝ˜ ์ˆ˜์ • #25 * ๐Ÿ’„ UI: close icon ์ถ”๊ฐ€ #25 * ๐Ÿ’„ UI: SearchSection margin ์ˆ˜์ • #24 * ๐Ÿ’„ UI: BigCard ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: SearchPage Tip ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์ˆ˜์ • #24 * โœจ feat: add alarm modal #25 * ๐Ÿ’„ UI: Banner UI ์ˆ˜์ • #24 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #25 * ๐Ÿ’„ UI: SavedTipSection Card Props ์ˆ˜์ • #24 * โ™ป๏ธ refactor: pํƒœ๊ทธ ์˜ค๋ฅ˜ ์ˆ˜์ • #24 * ๐Ÿ’„ UI: Design System ์ ์šฉ #24 * โ™ป๏ธ refactor: Console์˜ค๋ฅ˜ props attr DOM ๋žœ๋”๋ง ํ•ด๊ฒฐ #24 * ๐Ÿ’„ UI: errorMessage ์Šคํƒ€์ผ ์ถ”๊ฐ€ (๋นจ๊ฐ„ ํ…Œ๋‘๋ฆฌ) #34 * ๐Ÿ”ง config: ์—๋Ÿฌํ•ธ๋“ค๋ง์„ ์œ„ํ•œ useInput ์ปค์Šคํ…€ํ›… ์ถ”๊ฐ€ #34 * โœจ feat: ์ด๋ฉ”์ผ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ #34 * ๐Ÿ”ง config: ์ด๋ฉ”์ผ ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•œ validation ์ƒ์„ฑ #34 * ๐Ÿ“ฆ package: axios ์ถ”๊ฐ€ #34 * ๐Ÿ”ง config: errorHandler ์‚ญ์ œ์ œ #34 * โ™ป๏ธ refactor: ButtonBox ์‚ญ์ œ ํ›„ InputForm์— ํ•ฉ์น˜๊ธฐ๊ธฐ #34 * โœจ feat: ์ž๋™๋กœ๊ทธ์ธ ํด๋ฆญ ์‹œ ์ฒดํฌ๋ฐ•์Šค ํ™œ์„ฑํ™” #34 * Feat/#33 UI community page UI & CreateAndPostPage UI (#37) * ๐Ÿ’„ UI: recent/ likes / bookmarks ๊ธฐ๋Šฅ ์ˆ˜์ • #33 * ๐Ÿ’„ UI: Community Page Banner Component #33 * ๐Ÿ’„ UI: Community Page 1 ๊ตฌํ˜„ #33 * ๐Ÿ”ง config: --host ์ถ”๊ฐ€ #33 * ๐Ÿ’„ UI: plus ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #33 * ๐Ÿ’„ UI: Tag ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ • #33 * ๐Ÿ’„ UI: ์ด๋ฏธ์ง€ ์—…๋กœ๋” ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: Title ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: CreatePostPage ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: Categories ์ปดํฌ๋„ŒํŠธ ์žฌ์ˆ˜์ • #33 * ๐Ÿ’„ UI: SearchModal ๊ตฌํ˜„ #33 * ๐Ÿ’„ UI: SearchSection ์žฌ์ˆ˜์ • #33 * ๐Ÿ’„ UI: SearchModalBar ๊ตฌํ˜„ #33 * ๐Ÿ› fix : error ํ•ด๊ฒฐ๊ฒฐ * ๐Ÿ’„ UI: ํƒ€์ดํ‹€ ๋””์ž์ธ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ๋งˆ์ดํŽ˜์ด์ง€ UI ์‚ฌ์ด์ฆˆ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: Tag ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: Section ์ปดํฌ๋„ŒํŠธ UI ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ์ตœ๊ทผ์— ๋ณธ ๊ฟ€ํŒ ์ˆ˜์ • ์กฐ๊ฑด๋ถ€ ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์กฐ๊ฑด ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ํ”„๋กœํ•„์นด๋“œ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ํƒœ๊ทธ ๋ฐฐ๊ฒฝ์ƒ‰ props ์ถ”๊ฐ€ ๋ฐ ํฐ์ƒ‰์ผ ๋•Œ ์กฐ๊ฑด ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ํŽธ์ง‘ํ•˜๊ธฐ ๋ฒ„ํŠผ ์ถ”๊ฐ€ #29 * โœจ feat: profileEdit ๋ฒ„ํŠผ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ ๋ฐ onClick ์†์„ฑ ์ถ”๊ฐ€ #29 * โœจ feat: add ProfileEditModal router #29 * ๐Ÿ’„ UI: ๋“œ๋กญ๋‹ค์šด ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #29 * ๐Ÿ“ฆ package: ์ง€์—ญ ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ #29 * โœจ feat: profileEdit ๋ชจ๋‹ฌ ์ƒ์„ฑ #29 * โœจ feat: profileEdit ๋ชจ๋‹ฌ ์—ฐ๊ฒฐ #29 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #29 * ๐Ÿ”ง config: ๋นŒ๋“œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #29 * โœ๏ธ Typo: ํ•„์š”์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ #29 * โœจ feat: interestEdit ๋ฒ„ํŠผ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ๋ฒ„ํŠผ padding ์ˆ˜์ • #29 * โœจ feat: interestEdit ๋ชจ๋‹ฌ ์ƒ์„ฑ #29 * โœจ feat: interestEdit ๋ชจ๋‹ฌ ์—ฐ๊ฒฐ #29 * โœจ feat: ๋ชจ๋‹ฌ ์ƒ๋‹จ์— X ๋‹ซ๊ธฐ ๋ฒ„ํŠผ ์ƒ์„ฑ #29 * โœจ feat: add SignUpPage ์ „์ฒด ์ˆ˜์ • #21 * โœจ feat: add SignupState ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ #21 * โœจ feat: button์— pageUp, pageDown, signUp ๋ณ€์ˆ˜ ์ƒ์„ฑ #21 * โœจ feat: Section1 ์•ฝ๊ด€ ๋™์˜ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: button์— disabled ์†์„ฑ ์ƒ์„ฑ #21 * โœจ feat: ํ•„์ˆ˜ ์•ฝ๊ด€ ๋™์˜์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: Button์— disabled ์Šคํƒ€์ผ ์ถ”๊ฐ€ #21 * โœจ feat: + ๋ˆŒ๋ €์„ ๋•Œ ์•ฝ๊ด€ ์ƒ์„ธ ๋‚ด์šฉ ๋„์šฐ๊ธฐ ์ถ”๊ฐ€ #21 * โœจ feat: button์— emailCheck ๋ณ€์ˆ˜ ์ƒ์„ฑ #21 * โœจ feat: Section2 ์ด๋ฉ”์ผ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: Section3 ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * ๐Ÿ’„ UI: ์ œ๋ชฉ ์ƒ‰์ƒ primary[700]์œผ๋กœ ๋ณ€๊ฒฝ #21 * โœจ feat: Section4 ๊ฐœ์ธ์ •๋ณด ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: Section4 ๋‹ค์Œ ๋ฒ„ํŠผ ์ถ”๊ฐ€ ์ˆ˜์ • #21 * โœจ feat: Section5 ๊ด€์‹ฌ์‚ฌ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ #21 * โœจ feat: ํšŒ์›๊ฐ€์ž… ์™„๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ฉ”์ธํ™”๋ฉด์œผ๋กœ #21 * โœจ feat: Section4 ํ”„๋กœํ•„ ์นด๋ฉ”๋ผ ์ปค์„œ ํฌ์ธํ„ฐ #21 * โœจ feat: ๋‹‰๋„ค์ž„ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœจ feat: ์ด๋ฉ”์ผ ๋ฐ ์ธ์ฆ๋ฒˆํ˜ธ ํ•„์ˆ˜ ์ž…๋ ฅ์— ๋”ฐ๋ฅธ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” #21 * โœ๏ธ Typo: ์„น์…˜ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ๋ณ€๊ฒฝ #21 * ๐Ÿ’„ UI: ๋ฒ„ํŠผ ๊ธ€์ž์ˆ˜์— ๋งž๊ฒŒ ์„ ํƒ์ƒ์ž ํฌ๊ธฐ ์ˆ˜์ • ๋ฐ font style ์ถ”๊ฐ€ #29 * ๐Ÿ’„ UI: ์ž๋™๋กœ๊ทธ์ธ ์ฒดํฌ๋ฐ•์Šค ์ƒ‰์ƒ ๋ณ€๊ฒฝ #34 * Feat/#38 pagination ๊ตฌํ˜„ & Skeleton UI TipSection (#40) * ๐Ÿ”ง config: .env gitignore ์„ค์ • #38 * ๐Ÿ”ง config: axios, react-query ์„ค์น˜ #38 * ๐Ÿ”ง config: ReactQueryDevtools, queryClient ์„ค์ • #38 * โœจ feat: axios ๊ธฐ๋ณธ hook #38 * ๐Ÿ’„ UI: dummyData ์ƒ์„ฑ #38 * โœจ feat: useGetTips hook ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection Component ์ˆ˜์ • #38 * ๐Ÿ’„ UI: TipsSection Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: Props ๋กœ ์ธํ•œ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * โœจ feat: Pagination ๊ธฐ๋Šฅ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection ํƒ€์ž… ์ถ”๊ฐ€ #38 * โœจ feat: SkeletonCard UI ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: SkeletonBigCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #38 * # UI: RecommendTips ๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: CommunityPage TipSection ์ปดํฌ๋„ŒํŠธ Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: BigCard pํƒœ๊ทธ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * Feat/#46 feat quiz banner (#47) * ๐Ÿ”ง config: .env gitignore ์„ค์ • #38 * ๐Ÿ”ง config: axios, react-query ์„ค์น˜ #38 * ๐Ÿ”ง config: ReactQueryDevtools, queryClient ์„ค์ • #38 * โœจ feat: axios ๊ธฐ๋ณธ hook #38 * ๐Ÿ’„ UI: dummyData ์ƒ์„ฑ #38 * โœจ feat: useGetTips hook ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection Component ์ˆ˜์ • #38 * ๐Ÿ’„ UI: TipsSection Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: Props ๋กœ ์ธํ•œ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * โœจ feat: Pagination ๊ธฐ๋Šฅ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: TipsSection ํƒ€์ž… ์ถ”๊ฐ€ #38 * โœจ feat: SkeletonCard UI ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: SkeletonBigCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #38 * # UI: RecommendTips ๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ตฌํ˜„ #38 * ๐Ÿ’„ UI: CommunityPage TipSection ์ปดํฌ๋„ŒํŠธ Props ์ˆ˜์ • #38 * โ™ป๏ธ refactor: BigCard pํƒœ๊ทธ console ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #38 * ๐Ÿ”ง config: ์ƒํƒœ๊ด€๋ฆฌ zustand ์„ค์น˜ #41 * ๐Ÿ’„ UI: dummyCategories ํด๋” ์ด๋™ #41 * ๐Ÿ’„ UI: SearchBar Icon ์ˆ˜์ • #41 * ๐Ÿ’„ UI: DummyCat ์ถ”๊ฐ€ #41 * โœจ feat: CreateAndPost Post Api ์—ฐ๋™ #41 * โœจ feat: Complete Modal ๊ตฌํ˜„ #41 * ๐Ÿ”ง config: framer-motion ์„ค์น˜ #46 * ๐Ÿ’„ UI: Icon, character ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #46 * โœจ feat: quiz Store ๊ตฌํ˜„ #46 * ๐Ÿ’„ UI: QuizBox ํ–‰๋™ ๊ตฌํ˜„ #46 * ๐Ÿ”ง config: develop ๋ฌธ์ œ ํ•ด๊ฒฐ #46 * ๐Ÿšจ conflict ํ•ด๊ฒฐ #46 * ๐Ÿ’„ UI: Vecel ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #46 * โœจ feat: kakaocallbackํŽ˜์ด์ง€ ๊ตฌํ˜„ ๋ฐ ๋ผ์šฐํ„ฐ #49 * โœ๏ธ Typo: eslint ๋ฌด์‹œ ๋ฌธ๊ตฌ ์‚ญ์ œ #49 * โœจ feat: ํšŒ์›๊ฐ€์ž… ํด๋ฆญ ์‹œ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ #49 * โœจ feat: ํšŒ์› ์ •๋ณด ์ฐพ๊ธฐ ํŽ˜์ด์ง€ ์ƒ์„ฑ #49 * โœจ feat: ํšŒ์› ์ •๋ณด ์ฐพ๊ธฐ ํŽ˜์ด์ง€ ์—ฐ๊ฒฐ #49 * Feat/#43 UI save tip page (#50) * โœจ feat: SaveTipPage ๊ตฌํ˜„ #43 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ #43 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ณ€๊ฒฝ #43 * โœจ feat: SkeletonImage width 240px๋กœ ๋ณ€๊ฒฝ#43 * โœจ feat: ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„ #43 * โœจ feat: Card ์ปดํฌ๋„ŒํŠธ onClick ์†์„ฑ ์ถ”๊ฐ€ #43 * โœจ feat: ์นด๋“œ ์ปดํฌ๋„ŒํŠธ ํด๋ฆญ ์‹œ ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ #43 * โœจ feat: ๋งˆ์ดํŽ˜์ด์ง€ ์ตœ๊ทผ ๋ณธ ๊ฟ€ํŒ ์ƒ์„ธํŽ˜์ด์ง€ ์—ฐ๊ฒฐ #43 * โœจ feat: onClick ์†์„ฑ์— ?์„ ํƒ ์ถ”๊ฐ€ #43 --------- Co-authored-by: rael * Feat/#54 feat quiz modify and on click add (#56) * โœจ feat: BigCard OnClick ํ•จ์ˆ˜ ๊ตฌํ˜„ #54 * โ™ป๏ธ refactor: Exit Animation ๊ตฌํ˜„ ์™„๋ฃŒ #54 * โœจ feat: RecommedTip OnClick ์—ฐ๊ฒฐ #54 * โœจ feat: Post ์˜ค๋ฅ˜ ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ - ์„œ๋ฒ„ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ํ›„ ๋‹ค์‹œ ์‹œ๋„ ์˜ˆ์ • #54 * Feat/#36 UI magazine (#51) * ๐Ÿ”ง config: framer-motion ๋ฒ„์ „ ์ˆ˜์ • #36 * โœจ feat: add mind-map component #36 * โœจ feat: add card-grid component #36 * โ™ป๏ธ refactor: card์—์„œ cardInfo ๋ถ„๋ฆฌ #36 * ๐Ÿ’„ UI: add MagazinePage #36 * ๐Ÿ’„ UI: add MagazineDetailPage #36 * Feat/#53 api folder stucture (#55) * ๐Ÿ”ง config: framer-motion ๋ฒ„์ „ ์ˆ˜์ • #36 * โœจ feat: add mind-map component #36 * โœจ feat: add card-grid component #36 * โ™ป๏ธ refactor: card์—์„œ cardInfo ๋ถ„๋ฆฌ #36 * ๐Ÿ’„ UI: add MagazinePage #36 * ๐Ÿ’„ UI: add MagazineDetailPage #36 * ๐Ÿ”ฅ remove: index file from api folder #53 * ๐Ÿ”ฅ remove: queries folder from hooks #53 * โœจ feat: tip ๊ด€๋ จ api ํ˜ธ์ถœ ์ถ”๊ฐ€ #53 * โœจ feat: tip ๊ด€๋ จ query ์ถ”๊ฐ€ #53 * โ™ป๏ธ refactor: api ํ˜ธ์ถœ ๋ฐฉ์‹ ์ˆ˜์ • #53 * โœจ feat: policy api ์ถ”๊ฐ€ #53 * โœจ feat: policy query ์ถ”๊ฐ€ #53 * โœจ feat: title ์†์„ฑ ์ˆ˜์ • #53 * ๐Ÿ’ฌ comment: ์ฃผ์„ ์ˆ˜์ • #53 * Feat/#52 ๋žœ๋”ฉํŽ˜์ด์ง€, ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ชจ๋‹ฌ์ฐฝ UI (#57) * ๐Ÿ› bug: DOM ๊ฒฝ๊ณ ์ฐฝ ํ•ด๊ฒฐ #52 * ๐Ÿ’„ UI: ๋กœ๊ณ  ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ #52 * ๐Ÿ’„ UI: ์บ๋ฆญํ„ฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #52 * ๐Ÿ› bug: DOM ๊ฒฝ๊ณ ์ฐฝ ํ•ด๊ฒฐ #52 * ๐Ÿ’„ UI: ํ”„๋กœํ•„ ๋ชจ๋‹ฌ ๊ด€๋ จ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #52 * โœจ feat: ํ”„๋กœํ•„ ๋ชจ๋‹ฌ ๊ตฌํ˜„ #52 * โœจ feat: ๋žœ๋”ฉํŽ˜์ด์ง€ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธํ™” #52 * ๐Ÿ’„ UI: ๋žœ๋”ฉํŽ˜์ด์ง€ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜ #52 * ๐Ÿ’„ UI: dot ๋””์ž์ธ ์ˆ˜์ • #52 * Feat/#44 UI save tip detail page (#58) * โœจ feat: SaveTipDetail ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ๊ตฌํ˜„ #44 * โ™ป๏ธ refactor: PostDetail ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #44 * โ™ป๏ธ refactor: CommentView ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #44 * โœ๏ธ Typo: props ์ค‘๋ณต ์‚ญ์ œ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ์ž…๋ ฅ์ฐฝ ๊ตฌํ˜„ #44 * โœจ feat: ๋Œ“๊ธ€ ์ž…๋ ฅ ๊ธฐ๋Šฅ ๋ฐ ๋”๋ณด๊ธฐ ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€๋ชฉ๋ก gap ์ˆ˜์ • #44 * ๐Ÿ”ง config: .gitignore์— .env ์ถ”๊ฐ€ #44 * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ฐ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹ ์ˆ˜์ • #44 * โœ๏ธ Typo: ๋Œ“๊ธ€์— ... ์‚ญ์ œ #44 * โœ๏ธ Typo: ๋‹จ์–ด ์ˆ˜์ • #44 * โœ๏ธ Typo: ์˜คํƒ€ ์ˆ˜์ • #29 * ๐Ÿ’„ UI: ๊ธฐ์กด ๋Œ“๊ธ€ ์‚ญ์ œ #44 * ๐Ÿ’„ UI: ์ข‹์•„์š”, ์ €์žฅํ•˜๊ธฐ, ๊ณต์œ ํ•˜๊ธฐ ๋ฒ„ํŠผ ์ƒ์„ฑ ๋ฐ useState ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: PAGE_SIZE 5๊ฐœ๋กœ ์ˆ˜์ • #44 * ๐Ÿ’„ UI: SkeletonComment ๋Œ“๊ธ€ UI ๊ตฌํ˜„ #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ๋ฌดํ•œ์Šคํฌ๋กค ๊ตฌํ˜„ #44 * ๐Ÿ“ฆ package: ๋Œ“๊ธ€ ๋”๋ฏธ๋ฐ์ดํ„ฐ ์ˆ˜์ • #44 * ๐Ÿ’„ UI: ๋Œ“๊ธ€ ๋ฌดํ•œ์Šคํฌ๋กค 3๊ฐœ์”ฉ ๋กœ๋”ฉ #44 --------- Co-authored-by: rael * Fix/#59 fix search page modify (#61) * ๐Ÿ”จ fix: react Hook Rendering ์ˆœ์„œ ๋ณ€๊ฒฝ #59 * ๐Ÿ”จ fix: title Default ๊ฐ’ ์ œ๊ฑฐ ๋ฐ undefined ๋ฐฉ์ง€ #59 * Feat/#62 feat token zustand (#63) * โœจ feat: zustand ์ „์—ญ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ†ตํ•œ refresh Token ๊ตฌํ˜„ #62 * โœจ feat: hashtags 2์ค‘ ๋ฐฐ์—ด๋กœ post #62 * ๐Ÿ’„ UI: TipSection Animation ์ถ”๊ฐ€ #62 * ๐Ÿ’„ UI: height ๋ณ€๋™ #62 * โœจ feat: RoutePaths ์‚ฌ์šฉ #62 * โœจ feat: handleEmailLogin #49 * โœจ feat: ํ”„๋กœํ•„ ๋“œ๋ž๋‹ค์šด ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋กœ๊ทธ์•„์›ƒ ์ถ”๊ฐ€ #49 * โœจ feat: ๋กœ๊ทธ์ธ ์‹œ ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ”„๋กœํ•„๋กœ ๋ณ€๊ฒฝ #49 * โœจ feat: ์ „์—ญ์ƒํƒœ๊ด€๋ฆฌ๋กœ ๋กœ๊ทธ์ธ ์ƒํƒœ ๊ด€๋ฆฌ #49 * โœจ feat: ์ด๋ฉ”์ผ ๋กœ๊ทธ์ธ API ์—ฐ๊ฒฐ #49 * โœจ feat: User ์ •๋ณด ์—ฐ๊ฒฐ #49 * ๐Ÿ› bug: ์ค‘๋ณต ํŒŒ์ผ ์‚ญ์ œ์ œ * Feat/#64 feat main page modify (#68) * ๐Ÿ’„ UI: NavigationBar z-index ์ˆ˜์ • #64 * ๐Ÿ’ฌ comment: refresh ํ† ํฐ ์„ฑ๊ณต ํ™•์ธํ›„ ํ† ํฐ ์ฝ˜์†” ์ฃผ์„ํ™” #64 * ๐Ÿ’„ UI: DummyData id ์ถ”๊ฐ€ #64 * โœจ feat: Banner Animation ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #64 * โœจ feat: NavigationBar ๊ฐœ๋ฐœ์ž๋ชจ๋“œ์—์„œ ๋ฆฌ๋žœ๋”๋ง ๋ฌธ์ œ ์ž„์‹œ ํ•ด๊ฒฐ #64 * โœจ feat: Quiz Hook ๊ตฌํ˜„ #64 * โœจ feat: Search Hook ๊ตฌํ˜„ #64 * โœจ feat: TipSection Api ์—ฐ๋™ ๋ฐ ์ปดํฌ๋„ŒํŠธ ์žฌํ™œ์šฉ ํšจ์œจ ํ–ฅ์ƒ #64 * โ™ป๏ธ refactor: hashtags ์ด์ค‘ ๋ฐฐ์—ด์—์„œ ๊ทธ๋ƒฅ ๋ฐฐ์—ด๋กœ post #64 * โœจ feat: SearchPage Search Hook ์‚ฌ์šฉ ๋ฐ TipItem ํƒ€์ž… transform ์„ค์ • #64 * ๐Ÿ’„ UI: Categories UI ์  ์š”์†Œ ์žฌ๊ตฌ์„ฑ #64 * โœจ feat: Quiz API ์—ฐ๊ฒฐ ๋ฐ ํ™”๋ฉด ๊ตฌ์„ฑ #64 * โœจ feat: quizAnswer Hook ๊ตฌํ˜„ #64 * โœจ feat: QuizAnswer Hook ๊ตฌํ˜„ 2 #64 * โœจ feat: QuizAnswer Api ์—ฐ๊ฒฐ #64 * โ™ป๏ธ refactor: ํฐ ํ™”๋ฉด์—์„œ ๋ฐฐ๋„ˆ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ€๋กœ ์Šคํฌ๋กค ๋ฐœ์ƒ ๋ฌธ์ œ ํ•ด๊ฒฐ #64 * ๐Ÿ’ฌ comment: Quiz Skeleton UI ๊ตฌํ˜„์ „ ์ฃผ์„์ฒ˜๋ฆฌ #64 * โ™ป๏ธ refactor: axios-instance ์ž์ฒด์— ๊ถŒํ•œ ์ˆ˜์—ฌ #64 * ๐Ÿ”จ fix: ์ •๋‹ต์ผ ๋•Œ๋งŒ server๋กœ post #64 * โ™ป๏ธ refactor: quizAPI ํŒŒ์ผ ์ด๋ฆ„ ์ •๋ฆฌ ๋ฐ api ํ†ตํ•ฉ #64 * โ™ป๏ธ refactor: ์ˆ˜์ •๋œ hook ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ #64 * Feat/#73 feat create page modify (#74) * โœจ feat: ๊ธ€ ์ƒ์„ฑ์‹œ userID ์ถ”๊ฐ€ #73 * โœจ feat: TipCreate Api ๋ถ„๋ฆฌ #73 * โœจ feat: SearchModal Close์‹œ ์ž…๋ ฅ์ฐฝ ์ดˆ๊ธฐํ™” #73 * Feat/#75 UI challenge page UI (#77) * โœจ feat: ๊ธ€ ์ƒ์„ฑ์‹œ userID ์ถ”๊ฐ€ #73 * โœจ feat: TipCreate Api ๋ถ„๋ฆฌ #73 * โœจ feat: SearchModal Close์‹œ ์ž…๋ ฅ์ฐฝ ์ดˆ๊ธฐํ™” #73 * โœจ feat: FetchUser ํ›„ user.nickname ๋ถˆ๋Ÿฌ์˜ค๊ธฐ #75 * ๐Ÿ’„ UI: ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #75 * ๐Ÿ’„ UI: Card border-radius ์ˆ˜์ • #75 * โœจ feat: RoutePath์— Challenge ์ถ”๊ฐ€ #75 * โœจ feat: NumberCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: Challenge Banner ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: ChallengeHeader ๊ตฌํ˜„ #75 * ๐Ÿ’„ UI: Challenge TipSection ๊ตฌํ˜„ ๋ฐ InfiniteScroll / Skeleton UI ์ ์šฉ #75 * ๐Ÿ’„ UI: ChallengePage UI #75 * Feat/#79 feat image upload & ErrorPage & SearchTag (#80) * โœจ feat: Image Post ์ถ”๊ฐ€ #79 * โœจ feat: ErrorPage ๊ตฌํ˜„ ๋ฐ ์—ฐ๊ฒฐ #79 * โ™ป๏ธ refactor: SearchPage ์—๋Ÿฌ ๋ฐœ์ƒ ์ฝ”๋“œ ์ž„์‹œ ์กฐ์น˜ ์ถ”ํ›„ ์ˆ˜์ • ์˜ˆ์ • #79 * โœจ feat: Search Tag ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #79 * โœจ feat: Image Upload์‹œ ์—ฌ๋Ÿฌ ๋ฒˆ ์—…๋กœ๋“œ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ #79 * โ™ป๏ธ refactor: API interface Type ์„ค์ • #79 * Feat/#60 UI chatbot (#81) * โœจ feat: ์ฑ—๋ด‡ ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ „์†ก ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ๊ฒ€์ƒ‰๋ฐ” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ํŽ˜์ด์ง€ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์˜ค๋ฅธ์ชฝ ํ™”์‚ดํ‘œ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์‚ฌ์ด๋“œ๋ฐ” ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€ #60 * ๐Ÿ’ฌ comment: ์ฑ—๋ด‡ ์ฃผ์„ ์ถ”๊ฐ€ #60 * ๐Ÿ’„ UI: add chatbot icon #60 * โœจ feat: ์ฑ„ํŒ…๋ฐฉ ์ €์žฅ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #60 * โœจ feat: ์—”ํ„ฐ ํด๋ฆญ์‹œ ์ „์†ก ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #60 * โœจ feat: ๋ฒ„ํŠผ ์—ฐ๊ฒฐ #60 * โœจ feat: ์ฑ„ํŒ… api ์—ฐ๊ฒฐ #60 * ๐Ÿ’„ UI: ์ฑ—๋ด‡ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜ #60 * โœจ feat: ๋ฒ„ํŠผ๋ณ„ ์งˆ๋ฌธ ํ…์ŠคํŠธ ์ถ”๊ฐ€ #60 * ๐Ÿ› bug: ์ฒซํด๋ฆญ ์ฑ„ํŒ… ์•ˆ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ #60 * ๐Ÿ”จ fix: ๋ผ์šฐํŠธ ๋จธ์ง€ ํ•ด๊ฒฐ #60 * Feat/#85 feat main page filter & chatbot Icon (#87) * ๐Ÿ’„ UI: ChatBot Icon ์ถ”๊ฐ€ #85 * โœจ feat: ๋‚ ์งœ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #85 * ๐Ÿ”ฅ remove: RecommedTipSection ์‚ญ์ œ #85 * โ™ป๏ธ refactor: SearchApi Tag๋กœ๋งŒ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ query ์˜ต์…”๋„ ์ถ”๊ฐ€ #85 * โœจ feat: user HashTag Get, Post #85 * โ™ป๏ธ refactor: TipSection ์žฌํ™œ์šฉ์„ฑ ๊ทน๋Œ€ํ™” / useTipList, useSearchList ์กฐ๊ฑด๋ฌธ์„ ํ†ตํ•ด ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ / Card ์™€ BigCard ์กฐ๊ฑด๋ฌธ์œผ๋กœ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ #85 * ๐Ÿ’„ UI: ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ title ๋ฌธ๊ตฌ ์ˆ˜์ • ๋ฐ ๋ฐ์ดํ„ฐ ์ˆ˜์ • #85 * โ™ป๏ธ refactor: useSearchList Sorted ์˜ต์…˜ ์ถ”๊ฐ€ #85 * โ™ป๏ธ refactor: defaultSort Props ์ถ”๊ฐ€ #85 * ๐Ÿ’„ UI: ์นดํ…Œ๊ณ ๋ฆฌ visible default ์ˆ˜์ • #85 * โœ๏ธ typo: bookmarks -> saves #85 * ๐Ÿ”ฅ remove: console.log ์ œ๊ฑฐ #85 * โ™ป๏ธ refactor: query ์ถ”๊ฐ€ ๋ฐ isMoreLimit ์กฐ๊ฑด ์ถ”๊ฐ€ #85 * ๐Ÿ”ฅ remove: console ์ œ๊ฑฐ #85 * Feat/#84 UI my challenge (#88) * โœจ feat: MyChallenge Path ์ถ”๊ฐ€ #84 * ๐Ÿ”จ fix: navigate ์ฃผ์†Œ ์ˆ˜์ • #84 * ๐Ÿ’„ UI: MyChallenge UI ๊ตฌํ˜„ #84 * ๐Ÿ’„ UI: Challenge Tip Skeleton ์ถ”๊ฐ€ #84 * ๐Ÿ’„ UI: cursor: pointer ์ถ”๊ฐ€ ์™„๋ฃŒ #84 * Feat/#90 UI challenge detail page (#91) * ๐Ÿ”ง config: ์ฑŒ๋ฆฐ์ € ์ƒ์„ธ ํŽ˜์ด์ง€ ๋ผ์šฐํ„ฐ ์—ฐ๊ฒฐ #90 * โœจ feat: onCardClick ์†์„ฑ ์ถ”๊ฐ€ #90 * โœจ feat: onCardClick ํ•จ์ˆ˜ ์ถ”๊ฐ€ [#90] * ๐Ÿ“ฆ package: ๋”๋ฏธ๋ฐ์ดํ„ฐ #90 * โœจ feat: ChallengeDetailPage ์ถ”๊ฐ€ #90 * โœจ feat: ChallengeDetail ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #90 * โœจ feat: ChallengeComment ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #90 * โ™ป๏ธ refactor: FloatingToggleBtn ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ #90 * ๐Ÿ’„ UI: ์ฑŒ๋ฆฐ์ง€ ์ƒ์„ธ ํŽ˜์ด์ง€ UI ๊ตฌํ˜„ #90 * ๐Ÿ’„ UI: ์ฑŒ๋ฆฐ์ง€ ์ƒ์„ธ ํŽ˜์ด์ง€ ์ฐธ๊ฐ€์ž ํ›„๊ธฐ UI ๊ตฌํ˜„ #90 * โœจ feat: handleCardClick ์ถ”๊ฐ€ [#90] * Feat/#76 feature page api (#92) * ๐Ÿ’„ UI: ๋งˆ์ดํŽ˜์ด์ง€ UI ์ˆ˜์ • #76 * โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ (์ด๋ฏธ์ง€ ์ˆ˜์ • api ํ•„์š”) #76 * โœจ feat: ์ตœ๊ทผ ๋ณธ ๊ฟ€ํŒ ๊ธฐ๋Šฅ (์ €์žฅ๋œ ๊ฟ€ํŒ ํŽ˜์ด์ง€๊นŒ์ง€๋งŒ ์ถ”๊ฐ€๋จ/๋ฉ”์ธ, ๋งค๊ฑฐ์ง„ ๋“ฑ๋“ฑ handleCardClick ์ถ”๊ฐ€์ˆ˜์ • ํ•ด์•ผํ•จ.) #76 * โœจ feat: ๋ฌดํ•œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ํ•ด๊ฒฐ #76 * ๐Ÿ“ฆ package: InfiniteQuery ์ถ”๊ฐ€ #76 * โœจ feat: getSavedTips api ์ถ”๊ฐ€ (์•„์ง ์—๋Ÿฌ ํ•ด๊ฒฐX) #76 * โœจ feat: useSaveTipList ์ฟผ๋ฆฌ ์ด์šฉํ•ด์„œ ๋ฌดํ•œ์Šคํฌ๋กค ์ถ”๊ฐ€ ์‹œ๋„ #76 * โœจ feat: api ์—ฐ๊ฒฐ ์ค‘ #76 * โœจ feat: tip ํ˜•์‹ ํ†ต์ผ #76 * โœจ feat: ์นด์นด์˜ค ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #76 * โœจ feat: getTipDetail api, useTipDetail ์ถ”๊ฐ€ #76 * โœจ feat: dummydata ์‚ญ์ œ ํ›„ api ์—ฐ๊ฒฐ ์‹œ๋„ #76 * โœจ feat: comment get, post, put, delete api ์ถ”๊ฐ€ #76 * โœจ feat: ์ข‹์•„์š”์™€ ๋ถ๋งˆํฌ ํ† ๊ธ€ api ์ถ”๊ฐ€ #76 * โœจ feat: ์ข‹์•„์š”์™€ ๋ถ๋งˆํฌ mutation ์ถ”๊ฐ€ #76 * ๐Ÿ’„ UI: ํ† ๊ธ€ ๋ฒ„ํŠผ๋“ค ์ปดํฌ๋„ŒํŠธํ™” #76 * โ™ป๏ธ refactor: ์ปดํฌ๋„ŒํŠธํ™” ๋ฐ˜์˜ #76 * ๐Ÿ’„ UI: ๊ฟ€ํŒ ์ƒ์„ธ ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ #76 * โ™ป๏ธ refactor: ์ €์žฅ ์œ„์น˜ ๋ณ€๊ฒฝ #76 * โœจ feat: ์ €์žฅ ๊ฟ€ํŒ ๋ฐ˜ํ™˜๊ฐ’ ์ˆ˜์ • #76 * ๐Ÿ’„ UI: modify width #76 * ๐Ÿ’„ UI: remove text #76 * โœจ feat: ์ €์žฅํ•œ ๊ฟ€ํŒ api ์—ฐ๊ฒฐ #76 * โœจ feat: ์นด์นด์˜ค ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์˜ค๋ฅ˜ ์ˆ˜์ • [#76] * ๐Ÿ’„ UI: cursor pointer ์ถ”๊ฐ€ [#76] * โœจ feat: ์ด๋ฉ”์ผ ์ž…๋ ฅ ํผ api ์ˆ˜์ • #76 * โœจ feat: ์ข‹์•„์š” ๋ฐ ์ €์žฅ ์—ฌ๋ถ€ ์ €์žฅ #76 * ๐Ÿ’ฌ comment: ์ฃผ์„ ์‚ญ์ œ #76 * โ™ป๏ธ refactor: DTO ์ˆ˜์ •์‚ฌํ•ญํ•ญ ๋ฐ˜์˜ #76 * โœจ feat: ๋Œ“๊ธ€ api ์—ฐ๊ฒฐ #76 * โœจ feat: ๋Œ“๊ธ€ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #76 * ๐Ÿ› bug: ์นด์นด์˜ค ๊ณต์œ  #76 * โœจ feat: ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ ๋ฐ˜์˜ #76 * ๐Ÿ› bug: ํƒ€์ž… ์—๋Ÿฌ ํ•ด๊ฒฐ #76 * โ™ป๏ธ refactor: ๋Œ“๊ธ€ ์ธํ„ฐํŽ˜์ด์Šค ์ ์šฉ #76 * โœจ feat: ํšŒ์›๊ฐ€์ž… api ์—ฐ๊ฒฐ #76 * โœจ feat: userStore updateProfile ์ถ”๊ฐ€ #76 * โœจ feat: ์˜ค๋ฅ˜ ์ˆ˜์ • #76 * ๋ณต์ œ ๋ฌธ์„œ ์‚ญ์ œ * โœจ feat: ํšŒ์›๊ฐ€์ž… ์˜ค๋ฅ˜ ์ˆ˜์ •์ค‘ #76 --------- Co-authored-by: rael Co-authored-by: Head-ddy <80982532+Head-ddy@users.noreply.github.com> * Feat/#89 Navigation bar UI (#93) * ๐Ÿ’„ UI: ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ˜ธ๋ฒ„๋ง ์ถ”๊ฐ€ #89 * โœจ feat: ํŒŒ๋น„์ฝ˜ ์ถ”๊ฐ€ #89 * ๐Ÿ› bug: ์ถฉ๋Œ ์—๋Ÿฌ ํ•ด๊ฒฐ * Feat/#82 api magazine (#94) * ๐Ÿ’„ UI: ๋งค๊ฑฐ์ง„ ์บ๋ฆญํ„ฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ #82 * โœจ feat: ์ธ๊ธฐ ํ•ด์‹œํ…Œ๊ทธ ์—ฐ๊ฒฐ #82 * โœจ feat: ๋งค๊ฑฐ์ง„ ์ƒ์„ธ ์ •๋ณด api ์—ฐ๊ฒฐ #82 * โœจ feat: ์ „์ฒด ์ด๋ฏธ์ง€๋ณด๊ธฐ ๋ชจ๋‹ฌ ์ถ”๊ฐ€ #82 * ๐Ÿ› bug: ์ •์ฑ… api ์ธํ„ฐํŽ˜์ด์Šค ์ˆ˜์ • #82 * ๐Ÿ› bug: ํƒ€์ž… ์—๋Ÿฌ๋Ÿฌ * Fix/#96 fix landing page access (#98) * โœจ feat: AuthWrapper ํ†ตํ•ด ๊ถŒํ•œ ์—†์ด ๋‹ค๋ฅธ ํŽ˜์ด์ง€ ์ ‘๊ทผ ์ œํ•œ #96 * โ™ป๏ธ refactor: ์‹ค์ œ accessToken ์œผ๋กœ ์ ‘๊ทผ #96 * โ™ป๏ธ refactor: refreshToken Default ๊ฐ’ null ์„ค์ • #96 * Feat/#66 fix signup modify (#99) * ๐Ÿ”ง config: gitignore ์ˆ˜์ • #66 * โœจ feat: ์ „์ฒด ์ด์šฉ์•ฝ๊ด€ ์ฒดํฌ๋ฐ•์Šค ์˜ค๋ฅ˜ ์ˆ˜์ • #66 * โœ๏ธ Typo: ํ•„์š”์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ #66 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ๋‹‰๋„ค์ž„ ์ƒํƒœ ๊ฒ€์ฆ ๋ฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ๋‹‰๋„ค์ž„ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ #66 * ๐Ÿ’„ UI: ํšŒ์›๊ฐ€์ž… ๋‹จ๊ณ„ UI ์ˆ˜์ • #66 * โœจ feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ถ”๊ฐ€ #66 * โœจ feat: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต! #66 * โœจ feat: ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ ๋ฐ ๋ฒ„ํŠผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ #66 * โœจ feat: api ์ˆ˜์ • #66 * โœจ feat: ํšŒ์›๊ฐ€์ž… ํ›„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ #66 * โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ #66 * โœจ feat: ์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ ์ˆ˜์ • #66 * ๐Ÿ’„ UI: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต alert ์ถ”๊ฐ€ #66 * Fix/#97/saved tips (#100) * โœจ feat: ์ƒ๋‹จ ์Šคํฌ๋กค ๊ธฐ๋Šฅ #97 * โœจ feat: ๋กœ๊ณ  ์ด๋ฏธ์ง€์—๋„ ์ƒ๋‹จ ์Šคํฌ๋กค ๊ธฐ๋Šฅ ์ถ”๊ฐ€ #97 * ๐Ÿ’„ UI: ํฌ์ธํ„ฐ ์ถ”๊ฐ€ #97 * โœจ feat: ์ข‹์•„์š” & ์ €์žฅ ์ˆ˜ ์ถ”๊ฐ€ #97 * โœจ feat: ์‚ฌ์ง„ ๊ฐœ์ˆ˜์— ๋”ฐ๋ฅธ ๊ทธ๋ฆฌ๋“œ ์ถ”๊ฐ€ #97 * โœจ feat: ์‚ฌ์ง„ 5๊ฐœ ์ž„์‹œ ๊ทธ๋ฆฌ๋“œ #97 * โœจ feat: profile image ์ถ”๊ฐ€ #97 * Feat/#69 feature kakao login (#102) * โœจ feat: ์นด์นด๋กœ ๋กœ๊ทธ์ธ ์—”๋“œํฌ์ธํŠธ ์ˆ˜์ • #69 * โœจ feat: ์นด์นด์˜ค ๋กœ๊ทธ์ธ #69 * โœจ feat: ํ•ธ๋“ค ์นด์นด์˜ค ๋กœ๊ทธ์ธ #69 * ๐Ÿ› bug: ์ถฉ๋Œ ์—๋Ÿฌ๋Ÿฌ #69 * โœจ feat: ํ•ธ๋“ค ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ˆ˜์ • #69 * โœจ feat: ํ•ธ๋“ค ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์ˆ˜์ •์ค‘... #69 * ๐Ÿ› bug: ์นด์นด์˜ค ๋กœ๊ทธ์ธ ํ•ด๊ฒฐ #69 --------- Co-authored-by: rael * Feat/#104 fix demo modify (#105) * ๐Ÿ”ง fix: undefined ๋ฌธ์ œ ํ•ด๊ฒฐ #104 * โœจ feat: RecentTip ์ถ”๊ฐ€ #104 * ๐Ÿ’„ UI: ๋‚ ์งœ UI ์ˆ˜์ • #104 --------- Co-authored-by: rael Co-authored-by: Minji Kim Co-authored-by: Kim Minji <68258295+minzee09@users.noreply.github.com> Co-authored-by: Head-ddy <80982532+Head-ddy@users.noreply.github.com> Co-authored-by: Rael --- umc-master/src/pages/main/components/TipsSection.tsx | 11 +++++++---- umc-master/src/pages/mypage/components/RecentTips.tsx | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/umc-master/src/pages/main/components/TipsSection.tsx b/umc-master/src/pages/main/components/TipsSection.tsx index 61eebba..99a2b6d 100644 --- a/umc-master/src/pages/main/components/TipsSection.tsx +++ b/umc-master/src/pages/main/components/TipsSection.tsx @@ -12,7 +12,7 @@ import { AnimatePresence, motion } from 'framer-motion'; import { useSearchList } from '@apis/queries/useSearchList'; import BigCard from '@components/Card/BigCard'; import SkeletonBigCard from '@components/Skeleton/SkeletonBigCard'; - +import { recentStore } from '@store/recentStore'; interface TipsSectionProps { title?: string; showArrows?: boolean; @@ -146,8 +146,11 @@ const TipsSection: React.FC = ({ if (isError) return
Something went wrong...
; // ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ํ‘œ์‹œ - const handleCardClick = (id: number) => { - navigate(`/save-tip/${id}`); + const { addRecentTip } = recentStore(); // Zustand ์ƒํƒœ ๊ฐ€์ ธ์˜ค๊ธฐ + + const handleCardClick = (tip: TipItem) => { + addRecentTip(tip); // ์ตœ๊ทผ ๋ณธ ํŒ์œผ๋กœ ์ €์žฅ + navigate(`/save-tip/${tip.tipId}`); // ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ }; const handleSlide = (direction: number) => { @@ -212,7 +215,7 @@ const TipsSection: React.FC = ({ likes={item.likesCount || 0} bookmarks={item.savesCount || 0} date={item.createdAt?.slice(0, 10) || ''} - onClick={() => handleCardClick(item.tipId)} + onClick={() => handleCardClick(item)} /> ))} diff --git a/umc-master/src/pages/mypage/components/RecentTips.tsx b/umc-master/src/pages/mypage/components/RecentTips.tsx index 59a56c6..9f974ea 100644 --- a/umc-master/src/pages/mypage/components/RecentTips.tsx +++ b/umc-master/src/pages/mypage/components/RecentTips.tsx @@ -4,6 +4,7 @@ import Typography from '@components/common/typography'; import { useNavigate } from 'react-router-dom'; import { recentStore } from '@store/recentStore'; import { useEffect } from 'react'; +import dummyImage from '@assets/dummyImage/dummy.jpeg'; const RecentTips: React.FC = () => { const theme = useTheme(); @@ -33,11 +34,11 @@ const RecentTips: React.FC = () => { {recentTips.map((item) => ( handleCardClick(String(item.tipId))} /> ))} From 75819f122d0afed13776e60541baf997f498ae3c Mon Sep 17 00:00:00 2001 From: Minji Kim Date: Thu, 6 Nov 2025 01:27:52 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=A9=B9=20chore:=20organize=20images?= =?UTF-8?q?=20#107?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../challenge/compoents/ChallengeHeader.tsx | 2 +- .../pages/challenge/compoents/TipSection.tsx | 15 +- .../src/pages/magazine/MagazinePage.tsx | 44 +++++- .../mychallenge/components/TipSection.tsx | 12 +- umc-master/src/pages/mychallenge/dummydata.ts | 137 ++++++++++++++++++ 5 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 umc-master/src/pages/mychallenge/dummydata.ts diff --git a/umc-master/src/pages/challenge/compoents/ChallengeHeader.tsx b/umc-master/src/pages/challenge/compoents/ChallengeHeader.tsx index e027f53..c61eae5 100644 --- a/umc-master/src/pages/challenge/compoents/ChallengeHeader.tsx +++ b/umc-master/src/pages/challenge/compoents/ChallengeHeader.tsx @@ -16,9 +16,9 @@ const ChallengeHeader: React.FC = ({ onSortChange, }) => { const categories = [ + { id: 'cleaning', label: '์ฒญ์†Œ' }, { id: 'season', label: '๊ณ„์ ˆ' }, { id: 'fashion', label: 'ํŒจ์…˜' }, - { id: 'cleaning', label: '์ฒญ์†Œ' }, { id: 'cooking', label: '์š”๋ฆฌ/์‚ฌ๊ณ„์ ˆ' }, { id: 'games', label: '๊ฒŒ์ž„ํ˜•/๋ถ„๋ฆฌํ•˜๊ธฐ' }, { id: 'etc', label: 'ํ›„๊ธฐ' }, diff --git a/umc-master/src/pages/challenge/compoents/TipSection.tsx b/umc-master/src/pages/challenge/compoents/TipSection.tsx index e23d758..e8267f4 100644 --- a/umc-master/src/pages/challenge/compoents/TipSection.tsx +++ b/umc-master/src/pages/challenge/compoents/TipSection.tsx @@ -1,10 +1,10 @@ import { useState, useEffect, useRef, useCallback, useMemo } from 'react'; import ChallengeHeader from './ChallengeHeader'; import NumberCard from '@components/Card/NumberCard'; -import dummyImage from '@assets/dummyImage/clean.png'; import styled from 'styled-components'; import SkeletonCard from '@components/Skeleton/SkeletonCard'; import { useNavigate } from 'react-router-dom'; +import { dummyImage, dummyText } from '@pages/mychallenge/dummydata'; interface Tip { id: number; @@ -18,16 +18,15 @@ interface Tip { const PAGE_SIZE = 10; -/* ์ž„์‹œ ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ํ•จ์ˆ˜ */ -const generateDummyData = (count: number, startId: number): Tip[] => { +const generateDummyData = (count: number, startId: number, images: string[], texts: string[]): Tip[] => { return Array.from({ length: count }, (_, index) => { const randomDaysAgo = Math.floor(Math.random() * 30); const date = new Date(); date.setDate(date.getDate() - randomDaysAgo); return { id: startId + index, - image: dummyImage, - text: `์ฒญ์†Œ๋ฉ”์ดํ‚น๊ฐ€์ด๋“œ ${startId + index}`, + image: images[Math.floor(Math.random() * images.length)], // ๋žœ๋ค ์ด๋ฏธ์ง€ + text: texts[Math.floor(Math.random() * texts.length)], // ๋žœ๋ค ํ…์ŠคํŠธ likes: Math.floor(Math.random() * 5000), bookmarks: Math.floor(Math.random() * 5000), date: date.toISOString().slice(0, 10), @@ -38,7 +37,7 @@ const generateDummyData = (count: number, startId: number): Tip[] => { const TipSection = () => { const [sortBy, setSortBy] = useState<'users' | 'latest'>('users'); - const [selectedCategory, setSelectedCategory] = useState('season'); + const [selectedCategory, setSelectedCategory] = useState('cleaning'); const [allData, setAllData] = useState([]); const [loadedCount, setLoadedCount] = useState(PAGE_SIZE); const [isLoading, setIsLoading] = useState(false); @@ -51,7 +50,7 @@ const TipSection = () => { setIsLoading(true); const timer = setTimeout(() => { - const dummyData = generateDummyData(100, 1); + const dummyData = generateDummyData(100, 1, dummyImage, dummyText); setAllData(dummyData); setIsLoading(false); }, 1000); @@ -126,7 +125,7 @@ const TipSection = () => { ))} ) : ( - + )} {hasMore && !isLoading &&
} diff --git a/umc-master/src/pages/magazine/MagazinePage.tsx b/umc-master/src/pages/magazine/MagazinePage.tsx index d25c226..42c9c13 100644 --- a/umc-master/src/pages/magazine/MagazinePage.tsx +++ b/umc-master/src/pages/magazine/MagazinePage.tsx @@ -7,14 +7,41 @@ import MindMap from './components/mindMap'; import CardGrid, { CardGridData } from './components/cardGrid'; import { usePolicies } from '@apis/queries/usePolicyQueries'; +const IMAGES = [ + 'https://i.pinimg.com/736x/06/e6/e5/06e6e5415db0dc7aa3aaba1b93f03b20.jpg', + 'https://i.pinimg.com/1200x/7c/6f/7c/7c6f7c596654678b7400ef2c07c086ad.jpg', + 'https://i.pinimg.com/1200x/ad/24/04/ad24045a4a3ae15c6d765b3b711f61c1.jpg', + 'https://i.pinimg.com/1200x/7d/78/fa/7d78faa3c633bf5fde231e1b446bc4fb.jpg', + 'https://i.pinimg.com/1200x/12/76/a2/1276a2dc2749275436a49fb3561770ba.jpg', + 'https://i.pinimg.com/1200x/d8/0d/a9/d80da9b244d7de383b319457de475e89.jpg', + 'https://i.pinimg.com/1200x/cf/93/b1/cf93b11fac04e6790fab2f83e60b70cf.jpg', + 'https://i.pinimg.com/1200x/60/39/77/60397711931a8bbbdcb2d25493556a27.jpg', + 'https://i.pinimg.com/736x/62/6f/e8/626fe850e3fd8c62c9ad4126571112bf.jpg', +] as const; + +const TEXTS = [ + '์„ธํƒ ๊ฟ€ํŒ ๋ชจ์Œ', + '์š•์‹ค ์ฒญ์†Œ ๊ฐ€์ด๋“œ', + '๋ƒ‰์žฅ๊ณ  ์ •๋ฆฌ ๊ฟ€ํŒ', + '์ฃผ๋ฐฉ ์œ ๋ฆฌ์ฐฝ ์ฒญ์†Œ๋ฒ•', + '๊ฐ•์•„์ง€ ํ„ธ ์ฒญ์†Œ ๋ฐฉ๋ฒ•', + '๋นจ๋ž˜ ๋ƒ„์ƒˆ ์—†์• ๋Š” ๋ฒ•', + '์ „์ž๋ ˆ์ธ์ง€ ์ฐŒ๋“ ๋•Œ ์ œ๊ฑฐ', + '์ฒญ์†Œ ๋™์„  ์ตœ์ ํ™” ํŒ', + '์›๋ฃธ ๋ฏธ๋‹ˆ๋ฉ€ ์ •๋ฆฌ๋ฒ•', +] as const; + const generateDummyData = (): CardGridData[] => { + const randomDaysAgo = Math.floor(Math.random() * 30); + const date = new Date(); + date.setDate(date.getDate() - randomDaysAgo); return Array.from({ length: 9 }, (_, index) => ({ id: String(index + 1), - image: 'https://i.pinimg.com/736x/af/a0/76/afa07695334ef42a7864f09a0099a679.jpg', - text: `๋”๋ฏธ ๋ฐ์ดํ„ฐ ${index + 1}`, + image: IMAGES[index % IMAGES.length], + text: TEXTS[index % TEXTS.length], likes: Math.floor(Math.random() * 2000) + 1000, bookmarks: Math.floor(Math.random() * 2000) + 1000, - date: '2025.01.18', + date: date.toISOString().slice(0, 10), })); }; @@ -22,6 +49,15 @@ const MagazinePage = () => { const { data: policiesData } = usePolicies({ locationId: 17 }); const influencerData = generateDummyData(); + const influencerPolicies: PolicyData[] = influencerData.map((c) => ({ + id: Number(c.id), + title: c.text, + imageUrl: c.image, + likeCount: c.likes, + bookmarkCount: c.bookmarks, + createAt: c.date, + })); + useEffect(() => { window.scrollTo(0, 0); }, []); @@ -39,7 +75,7 @@ const MagazinePage = () => { <Typography variant="headingXxSmall">์ธํ”Œ๋ฃจ์–ธ์„œ ๊ฟ€ํŒ</Typography> - +
); diff --git a/umc-master/src/pages/mychallenge/components/TipSection.tsx b/umc-master/src/pages/mychallenge/components/TipSection.tsx index adaae57..78e6378 100644 --- a/umc-master/src/pages/mychallenge/components/TipSection.tsx +++ b/umc-master/src/pages/mychallenge/components/TipSection.tsx @@ -2,8 +2,8 @@ import { useState, useEffect, useMemo } from 'react'; import styled from 'styled-components'; import NumberCard from '@components/Card/NumberCard'; import SkeletonCard from '@components/Skeleton/SkeletonCard'; -import dummyImage from '@assets/dummyImage/clean.png'; import { useNavigate } from 'react-router-dom'; +import { dummyImage, dummyText } from '../dummydata'; interface Tip { id: number; @@ -16,15 +16,15 @@ interface Tip { } // ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ํ•จ์ˆ˜ (ํ•„์š”์— ๋”ฐ๋ผ ์œ ์ง€) -const generateDummyData = (count: number, startId: number): Tip[] => { +const generateDummyData = (count: number, startId: number, images: string[], texts: string[]): Tip[] => { return Array.from({ length: count }, (_, index) => { const randomDaysAgo = Math.floor(Math.random() * 30); const date = new Date(); date.setDate(date.getDate() - randomDaysAgo); return { id: startId + index, - image: dummyImage, - text: `์ฒญ์†Œ๋ฉ”์ดํ‚น๊ฐ€์ด๋“œ ${startId + index}`, + image: images[Math.floor(Math.random() * images.length)], // ๋žœ๋ค ์ด๋ฏธ์ง€ + text: texts[Math.floor(Math.random() * texts.length)], // ๋žœ๋ค ํ…์ŠคํŠธ likes: Math.floor(Math.random() * 5000), bookmarks: Math.floor(Math.random() * 5000), date: date.toISOString().slice(0, 10), @@ -44,7 +44,7 @@ const TipSection = () => { // 1์ดˆ ๋’ค์— ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์„ค์ • const timer = setTimeout(() => { - const dummyData = generateDummyData(100, 1); + const dummyData = generateDummyData(100, 1, dummyImage, dummyText); setAllData(dummyData); setIsLoading(false); }, 1000); @@ -83,7 +83,7 @@ const TipSection = () => { ))} ) : ( - + )} ); diff --git a/umc-master/src/pages/mychallenge/dummydata.ts b/umc-master/src/pages/mychallenge/dummydata.ts new file mode 100644 index 0000000..2b254b4 --- /dev/null +++ b/umc-master/src/pages/mychallenge/dummydata.ts @@ -0,0 +1,137 @@ +export const dummyText = [ + '์„ธํƒ ํšจ์œจ ์—…๊ทธ๋ ˆ์ด๋“œ 7์ผ ์ฑŒ๋ฆฐ์ง€', + '์š•์‹ค ๋ชฐ๋“œ ์ œ๋กœ ํ”„๋กœ์ ํŠธ', + '๋ƒ‰์žฅ๊ณ  ์ „์ฒด ๋ฆฌ์…‹ ์ •๋ฆฌ ๋ฏธ์…˜', + '์ฃผ๋ฐฉ ์œ ๋ฆฌ์ฐฝ ๋ฐ˜์ง์ด๊ฒŒ ๋„์ „', + '๋ฐ˜๋ ค๋™๋ฌผ ํ„ธ ์™„์ „ ์ œ๊ฑฐ ์ฑŒ๋ฆฐ์ง€', + '๋นจ๋ž˜ ๋ƒ„์ƒˆ ์žก๊ธฐ 3๋‹จ๊ณ„ ๋ฃจํ‹ด', + '์ „์ž๋ ˆ์ธ์ง€ ์ฐŒ๋“ ๋•Œ ์ œ๊ฑฐ ๋ฏธ์…˜', + '์ง‘ ์•ˆ ์ฒญ์†Œ ๋™์„  ์ค„์ด๊ธฐ ์ฑŒ๋ฆฐ์ง€', + '์›๋ฃธ ๋ฏธ๋‹ˆ๋ฉ€๋ผ์ดํ”„ ์‹ค์ฒœ ํ”„๋กœ์ ํŠธ', + '๊ฐ€๊ตฌ ๋จผ์ง€ ์“ธ์–ด๋‚ด๊ธฐ ๋ฐ์ด', + '๋ฒ ์ดํ‚น์†Œ๋‹ค ์ฒญ์†Œ ์‹คํ—˜ ๋ฏธ์…˜', + '์‹ฑํฌ๋Œ€ ๋ฌผ๋•Œ ๋ฐ•๋ฉธ ์ฑŒ๋ฆฐ์ง€', + '์š•์‹ค ๊ณฐํŒก์ด ํ‡ด์น˜ 7์ผ ๋„์ „', + '๊ฑฐ์šธ ์–ผ๋ฃฉ ์ œ๋กœ ์ŠคํŒŸ ๋ฏธ์…˜', + '๋‚˜๋งŒ์˜ ์ฒญ์†Œ ๋ฃจํ‹ด ๋งŒ๋“ค๊ธฐ ์ฑŒ๋ฆฐ์ง€', + '์˜ท์žฅ ๊ณต๊ฐ„ ํ™•๋ณด ๋Œ€์ž‘์ „', + '์ฒญ์†Œ๊ธฐ ํ•„ํ„ฐ ์ƒˆ๊ฒƒ์ฒ˜๋Ÿผ ์ฑŒ๋ฆฐ์ง€', + '์œ ๋ฆฌ์ฐฝ ๋ฌด์ž๊ตญ ๊ด‘ํƒ ๋ฏธ์…˜', + '์นดํŽซ ๋จธ๋ฆฌ์นด๋ฝ ์ œ๊ฑฐ ๋„์ „', + '์ฃผ๋ฐฉ ๋ƒ„์ƒˆ ์ œ๋กœ ํ”„๋กœ์ ํŠธ', + '๋จผ์ง€ ์—†๋Š” ์ง‘ ๋งŒ๋“ค๊ธฐ ์‹ค์ฒœ ์ฑŒ๋ฆฐ์ง€', + '์ง‘์•ˆ ๊ณต๊ธฐ ์ •ํ™” ํ”Œ๋žœํŠธ ์ฑŒ๋ฆฐ์ง€', + '์„ค๊ฑฐ์ง€ ์†๋„ 2๋ฐฐ ๋ฏธ์…˜', + '๋นจ๋ž˜ ๊ฑด์กฐ ๋ฝ€์†กํ•˜๊ฒŒ ์„ฑ๊ณตํ•˜๊ธฐ', + '์“ฐ๋ ˆ๊ธฐํ†ต ํƒˆ์ทจ ๋ฏธ์…˜', + '์ด๋ถˆ ์† ๋จผ์ง€ ์ œ๊ฑฐ ์บ ํŽ˜์ธ', + '์ „์ž์ œํ’ˆ ๋จผ์ง€ ์“ธ๊ธฐ ๋ฃจํ‹ด', + '์—์–ด์ปจ ํ•„ํ„ฐ ์ฒญ์†Œ ๋ฏธ์…˜', + '๋ฒ ๋ž€๋‹ค ํ™ˆ์นดํŽ˜ ์ •๋ฆฌ ํ”„๋กœ์ ํŠธ', + '์‹ ๋ฐœ ๋ƒ„์ƒˆ ์ œ๊ฑฐ 3์ผ ๋„์ „', + '๊ธฐ๋ฆ„๋•Œ ์—†๋Š” ์ฃผ๋ฐฉ ๋งŒ๋“ค๊ธฐ ์ฑŒ๋ฆฐ์ง€', + '๋ฐ˜๋ ค๋™๋ฌผ ํ„ธ ํด๋ฆฐ ์ง‘ ๋„์ „', + '๋ƒ‰์žฅ๊ณ  ์œ ํ†ต๊ธฐํ•œ ์ •๋ฆฌ ์ฑŒ๋ฆฐ์ง€', + '๋ฐ”๋‹ฅ ์–ผ๋ฃฉ ์ œ๊ฑฐ ๋ ˆ๋ฒจ์—… ๋ฏธ์…˜', + '์ปต๋ผ๋ฉด ์„ค๊ฑฐ์ง€ 1๋ถ„ ์ฑŒ๋ฆฐ์ง€', + '๊ฑธ๋ ˆ ์—†์ด ์ฒญ์†Œ ๋„์ „', + '์นดํŽซ ๋ƒ„์ƒˆ OUT ์ฑŒ๋ฆฐ์ง€', + '๋งคํŠธ๋ฆฌ์Šค ์ฒญ์†Œ D-Day', + '์„ธํƒ ์‹คํŒจ ๋ณต๊ตฌ ๋ฏธ์…˜', + '๋นจ๋ž˜ ์ƒ‰์ƒ ๋ถ„๋ฅ˜ ์ •๋ณต ์ฑŒ๋ฆฐ์ง€', + 'ํ™”์žฅ๋Œ€ ๋ฏธ๋‹ˆ๋ฉ€ ์ •๋ฆฌ ๋ฏธ์…˜', + '์ฐฝ๋ฌธ ๋ฐฉํ’ํ…Œ์ดํ”„ ๋ถ™์ด๊ธฐ ๋„์ „', + '์š•์‹ค ์ค„๋ˆˆ ์‚ด๋ฆฌ๊ธฐ ํ”„๋กœ์ ํŠธ', + '๋„๋งˆ ์‚ด๊ท  ์‹ค์ „ ์ฑŒ๋ฆฐ์ง€', + 'TV ํ™”๋ฉด ๋จผ์ง€ ์ œ๋กœ ๋ฏธ์…˜', + '์นœํ™˜๊ฒฝ ๋ฌผํ‹ฐ์Šˆ ๋งŒ๋“ค๊ธฐ ๋„์ „', + '์ˆ˜๋‚ฉํ•จ์œผ๋กœ ๊ณต๊ฐ„ ์ตœ์ ํ™” ์ฑŒ๋ฆฐ์ง€', + '๋นจ๋ž˜ ๋ƒ„์ƒˆ ๋ฐฉ์ง€ 3์ผ ๋ฃจํ‹ด', + '์ˆ˜์„ธ๋ฏธ ์œ„์ƒ ๊ด€๋ฆฌ ๋ฏธ์…˜', + '์‹ฑํฌ๋Œ€ ๋ฌผ์ž๊ตญ ์ง€์šฐ๊ธฐ ์ŠคํŒŸ ๋ฏธ์…˜', + '์ „์ž๋ ˆ์ธ์ง€ ๋ƒ„์ƒˆ ์ œ๊ฑฐ ํ”„๋กœ์ ํŠธ', + '๋ฒ ๋ž€๋‹ค ๋นจ๋ž˜๊ฑด์กฐ ์ตœ์ ํ™” ์ฑŒ๋ฆฐ์ง€', + '์˜ท์žฅ ๊ณฐํŒก์ด ์˜ˆ๋ฐฉ ์ฑŒ๋ฆฐ์ง€', + '์ปคํŠผ ์„ธํƒ ์‹คํ–‰ ๋ฏธ์…˜', + '์„ฌ์œ ์œ ์—ฐ์ œ ์—†์ด ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ฑŒ๋ฆฐ์ง€', + '๋ฆฌ๋ชจ์ปจ ์‚ด๊ท  ๋ฏธ์…˜', + '์„ธํƒ๊ธฐ ๋‚ด๋ถ€ ์ฒญ์†Œ ํ”„๋กœ์ ํŠธ', + '๋ฐ”๋‹ฅ ํƒ€์ž…๋ณ„ ์ฒญ์†Œ๋„๊ตฌ ์‹คํ—˜ ์ฑŒ๋ฆฐ์ง€', + '์–‘๋ง ๋นจ๋ฆฌ ๋ง๋ฆฌ๊ธฐ ํŠธ๋ฆญ ๋„์ „', + 'ํ”„๋ผ์ดํŒฌ ๋ˆŒ์–ด๋ถ™์Œ ์ œ๊ฑฐ ๋ฏธ์…˜', + '์นซ์†” ์‚ด๊ท  5๋ถ„ ์ฑŒ๋ฆฐ์ง€', + 'ํ˜„๊ด€ ์‹ ๋ฐœ ์ •๋ฆฌ ๋ฆฌ์…‹ ๋ฏธ์…˜', + '์นจ๊ตฌ ํ„ธ์–ด๋‚ด๊ธฐ ๋ชจ๋‹ ๋ฃจํ‹ด', + '๋ณ€๊ธฐ ๋ฌผ๋•Œ ๋ฐ•๋ฉธ ์‹ค์ „ ์ฑŒ๋ฆฐ์ง€', + '์ฃผ๋ฐฉ ์ˆ˜๋‚ฉ ์žฌ๋ฐฐ์น˜ ํ”„๋กœ์ ํŠธ', + '์ฒญ์†Œ ์‹œ๊ฐ„ ๋ฐ˜์œผ๋กœ ์ค„์ด๊ธฐ ๋ฏธ์…˜', + '์ •๋ฆฌ ์ „ ๋ฒ„๋ฆฌ๊ธฐ ๊ธฐ์ค€ ์„ค์ • ์ฑŒ๋ฆฐ์ง€', + '์ฒœ์žฅ ๋จผ์ง€ ๋‹ฆ๊ธฐ ๋ฏธ์…˜', + '๊ณฐํŒก์ด ์Šคํ”„๋ ˆ์ด DIY ์ฑŒ๋ฆฐ์ง€', + '๋…ธํŠธ๋ถ ํ‚ค๋ณด๋“œ ์ฒญ์†Œ ๋„์ „', + '๋งˆ์Šคํฌ ๋ณด๊ด€ ์œ„์ƒ ์ฑŒ๋ฆฐ์ง€', + '์žฅ๋‚œ๊ฐ ์‚ด๊ท  ๋ฏธ์…˜', + '๋ฐ˜๋ ค๋™๋ฌผ ๋ฐฅ๊ทธ๋ฆ‡ ์„ธ์ฒ™ ๋ฃจํ‹ด', + '์ฑ…์žฅ ๋จผ์ง€ OUT ์ฑŒ๋ฆฐ์ง€', + '๊ณ ๋ฌด์žฅ๊ฐ‘ ์˜ค๋ž˜ ์“ฐ๊ธฐ ์‹คํ—˜', + '๋ƒ„๋น„ ํƒ„ ์ž๊ตญ ์ง€์šฐ๊ธฐ ๋ฏธ์…˜', + '์ผ€์ด๋ธ” ์ •๋ฆฌ ๊น”๋”ํ•˜๊ฒŒ ์ฑŒ๋ฆฐ์ง€', + 'ํ™”์žฅ์†œ ๋Œ€์‹  ์ฒญ์†Œ๋„๊ตฌ ํ™œ์šฉ ์ฑŒ๋ฆฐ์ง€', + '์ง‘ ์ฒญ์†Œ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ์‹ค์ „ ๋ฏธ์…˜', + '๋ฐ”๋‹ฅ ๋ฌผ๊ฑธ๋ ˆ ์ˆœ์„œ ์ตœ์ ํ™” ์ฑŒ๋ฆฐ์ง€', + '์ฒญ์†Œ ์ŠคํŠธ๋ ˆ์Šค ์ค„์ด๊ธฐ ๋ฃจํ‹ด', + '์ฐฝ๋ฌธ ๋ฏธ์„ธ๋จผ์ง€ ์ฐจ๋‹จ ๋„์ „', + '๋ฒ„๋ฆฌ๊ธฐ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ์ •๋ฆฌ ์ฑŒ๋ฆฐ์ง€', + '๋ฐ€ํ์šฉ๊ธฐ ์–ผ๋ฃฉ ์ œ๊ฑฐ ์‹คํ—˜', + '์†๋•Œ ๋งŽ์€ ๊ณณ ์ง‘์ค‘ ์ฒญ์†Œ ๋ฏธ์…˜', + '์‹ ๋ฐœ์žฅ ๋ƒ„์ƒˆ ๋ฐ•๋ฉธ ํ”„๋กœ์ ํŠธ', + '์•ˆ ์ž…๋Š” ์˜ท ๋น„์šฐ๊ธฐ ์ฑŒ๋ฆฐ์ง€', + '์ƒํ™œ ๋ฏธ๋‹ˆ๋ฉ€ ์ˆ˜๋‚ฉ ๋„์ „', + '๊ธฐ๋ฆ„ ์˜ค์—ผ ์˜ท ์„ธํƒ ์‘๊ธ‰ ๋ฏธ์…˜', + '๋ƒ‰์žฅ๊ณ  ๋ƒ„์ƒˆ ์›์ธ ์ถ”์  ์ฑŒ๋ฆฐ์ง€', + '์š”๋ฆฌ ํ›„ ๊ธฐ๋ฆ„ ์—ฐ๊ธฐ ์ œ๊ฑฐ ๋ฏธ์…˜', + '์ฃผ๋ฐฉ ์“ฐ๋ ˆ๊ธฐ ์ค„์ด๊ธฐ ํ”„๋กœ์ ํŠธ', + '์•„๊ธฐ ์˜ท ์•ˆ์ „ ์„ธํƒ ๋ฃจํ‹ด', + '๋ฐœ์ž๊ตญ ์—†๋Š” ๋ฐ”๋‹ฅ ๋งŒ๋“ค๊ธฐ ์ฑŒ๋ฆฐ์ง€', + '์žฌ์‚ฌ์šฉ ์ฒญ์†Œ๋„๊ตฌ ์‹คํ—˜ ๋ฏธ์…˜', + '5๋ถ„ ์ •๋ฆฌ ์Šต๊ด€ ๋“ค์ด๊ธฐ ์ฑŒ๋ฆฐ์ง€', + '์นจ๋Œ€ ๋ฐ‘ ๋จผ์ง€ ์“ธ๊ธฐ ๋ฏธ์…˜', + '์„ ๋ฐ˜ ์ •๋ฆฌ ์ƒ‰์ƒ ์ •๋ ฌ ํ”„๋กœ์ ํŠธ', + '์ฒœ์—ฐ ์„ธ์ œ ์ง์ ‘ ๋งŒ๋“ค๊ธฐ ๋„์ „', + '์ฒญ์†Œํ•˜๋ฉด์„œ ๋“ฃ๋Š” ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ฑŒ๋ฆฐ์ง€', + '์ฃผ๋ง 30๋ถ„ ์ฒญ์†Œ ๋ฏธ์…˜', + '๋ถ„๋ฆฌ์ˆ˜๊ฑฐ ํ—ท๊ฐˆ๋ฆผ ํ•ด๊ฒฐ ํ”„๋กœ์ ํŠธ', + '์š•์‹ค ์œ ๋ฆฌ ๋ฌผ๋•Œ ์ œ๊ฑฐ ์ฑŒ๋ฆฐ์ง€', +]; + +export const dummyImage = [ + 'https://i.pinimg.com/736x/06/e6/e5/06e6e5415db0dc7aa3aaba1b93f03b20.jpg', + 'https://i.pinimg.com/1200x/7c/6f/7c/7c6f7c596654678b7400ef2c07c086ad.jpg', + 'https://i.pinimg.com/1200x/ad/24/04/ad24045a4a3ae15c6d765b3b711f61c1.jpg', + 'https://i.pinimg.com/1200x/7d/78/fa/7d78faa3c633bf5fde231e1b446bc4fb.jpg', + 'https://i.pinimg.com/1200x/12/76/a2/1276a2dc2749275436a49fb3561770ba.jpg', + 'https://i.pinimg.com/1200x/d8/0d/a9/d80da9b244d7de383b319457de475e89.jpg', + 'https://i.pinimg.com/1200x/cf/93/b1/cf93b11fac04e6790fab2f83e60b70cf.jpg', + 'https://i.pinimg.com/1200x/60/39/77/60397711931a8bbbdcb2d25493556a27.jpg', + 'https://i.pinimg.com/736x/62/6f/e8/626fe850e3fd8c62c9ad4126571112bf.jpg', + 'https://i.pinimg.com/736x/d2/61/35/d26135aa8f817737682d3d3589b3fa75.jpg', + 'https://i.pinimg.com/736x/be/0c/da/be0cdab6740eaa94e4bf65311188c464.jpg', + 'https://i.pinimg.com/736x/79/22/33/79223349ad21e1b39062ef2f6a456426.jpg', + 'https://i.pinimg.com/736x/18/6c/89/186c89559f3af60441287c50951221ee.jpg', + 'https://i.pinimg.com/1200x/6d/5d/e9/6d5de95a547745c7d7bd89dce36f1a21.jpg', + 'https://i.pinimg.com/1200x/e0/4f/8d/e04f8d546a74e3bfe597c3a2a21f47f1.jpg', + 'https://i.pinimg.com/1200x/a8/91/c9/a891c976daeb28498dbb45a4c82bea2c.jpg', + 'https://i.pinimg.com/1200x/33/3d/60/333d600f6fe8ade83159cfbab72ca404.jpg', + 'https://i.pinimg.com/736x/f4/40/db/f440db7021262be430ea92bb071d266b.jpg', + 'https://i.pinimg.com/736x/d4/b5/bb/d4b5bbba4b70be6f56bb5d35d548e4b3.jpg', + 'https://i.pinimg.com/1200x/f9/4e/4d/f94e4d3e4eadea9cb3d9cd8bc5f2f0cd.jpg', + 'https://i.pinimg.com/1200x/6c/14/d4/6c14d4ff5ce77a9b0ad6ffb2fed4ad71.jpg', + 'https://i.pinimg.com/736x/09/4a/d6/094ad6976c03c08f1b324c9972172b6f.jpg', + 'https://i.pinimg.com/1200x/09/70/8e/09708e37bea71d1daa2c1ff70b0c0901.jpg', + 'https://i.pinimg.com/736x/ed/38/66/ed38663596cc2b9472742b68c40b455b.jpg', + 'https://i.pinimg.com/1200x/da/8d/38/da8d3856b00b300c3edb466600a3ba9f.jpg', + 'https://i.pinimg.com/1200x/dd/28/20/dd282050b43ae6c2a4a789e7bec82fea.jpg', + 'https://i.pinimg.com/736x/23/72/fb/2372fbd717eb1ccb447830a774ca14dd.jpg', + 'https://i.pinimg.com/736x/14/5c/11/145c110257c3746aecd2f0b03349cb97.jpg', + 'https://i.pinimg.com/736x/37/a1/e9/37a1e93a266525cc3eb71effbc6f7d72.jpg', +];