Skip to content

Commit

Permalink
[Feature] - touroot v1.3.2 (#595)
Browse files Browse the repository at this point in the history
* [Feature] - ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ ์„ธํŒ… (#4)

* chore: ์ดˆ๊ธฐ package.json ์„ค์ •

* chore: .gitignore ์ถ”๊ฐ€

* chore: tsconfig.json ์ดˆ๊ธฐ ์„ค์ •

* chore: react ๋‚ด webpack ์„ธํŒ…

1. webpack ๊ด€๋ จ ์˜์กด์„ฑ ์ถ”๊ฐ€

2. build scrpit ์ˆ˜์ •

3. webpack.common.js ์ถ”๊ฐ€

4. public ๋””๋ ‰ํ„ฐ๋ฆฌ ๋‚ด index.html ์ถ”๊ฐ€

5. src ๋””๋ ‰ํ„ฐ๋ฆฌ ๋‚ด App.tsx ๋ฐ main.tsx ์ถ”๊ฐ€

* chore: prettier & eslint ์„ค์ •

* chore: emotion ์„ค์ •

* docs: pull request ํ…œํ”Œ๋ฆฟ ์ถ”๊ฐ€

* chore: package.json ๋‚ด broswerslist ๋ณ€๊ฒฝ

1%์—์„œ 5%๋กœ ๋ณ€๊ฒฝ(ํฌ๋กฌ, ์‚ฌํŒŒ๋ฆฌ, ์—ฃ์ง€๋งŒ ์ ์œ ์œจ์ด 5% ์ด์ƒ์ด๊ธฐ ๋•Œ๋ฌธ)

์‚ฌ์†Œํ•œ ์„ค์ •์œผ๋กœ ์ธํ•ด develop์— ๋ฐ”๋กœ push

* [Feature] - stylelint ์„ค์ • (#51)

* chore: stylelint ๊ด€๋ จ ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: stylelint ๊ทœ์น™ stylelintrc.json์— ์ถ”๊ฐ€

* chore: vscode ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

* [Feature] - ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#42)

* feat: ๊ธฐ๋ณธ ํฐํŠธ ์„ค์ •

1. webpack ๋‚ด asset/resource ์˜ต์…˜ ์ถ”๊ฐ€

2. pretendard ํฐํŠธ ์ถ”๊ฐ€

3. woff์— ๋Œ€ํ•œ ํƒ€์ž… ์ถ”๊ฐ€

4. globalStyle ๋‚ด ๊ธฐ๋ณธ ํฐํŠธ๋ฅผ pretendard๋กœ ๋ณ€๊ฒฝ

* feat: svg ๋‚ด asset ์„ค์ •

* feat: ThemeProvider ์ถ”๊ฐ€

1. theme ๊ด€๋ จ declare ํŒŒ์ผ ์ถ”๊ฐ€

2. theme ์ถ”๊ฐ€

3. theme์„ ThemeProvider ์ ์šฉ

* feat: svg๋ฅผ ์ปดํฌ๋„ŒํŠธ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ

1. @svgr/webpack ์˜์กด์„ฑ ์ถ”๊ฐ€

2. webpack.common.js ๋‚ด ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€(url, component ๋ชจ๋‘ ์‚ฌ์šฉ)

3. svg.d.ts ๋‚ด svg ๊ด€๋ จ ํƒ€์ž… ์„ค์ • ์ถ”๊ฐ€

* feat: font ๊ด€๋ จ local ํ•จ์ˆ˜ ์ถ”๊ฐ€

* feat: assets/index.ts ๋‚ด marker url ์„ค์ • ์ถ”๊ฐ€

* feat: tanstack query ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: prettier ๋‚ด sort ์ˆœ์„œ ๋ณ€๊ฒฝ

* chore: ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ธํŒ…

1. dotenv-webpack ์˜์กด์„ฑ ์ถ”๊ฐ€

2. webpack config ํŒŒ์ผ ๋‚ด DotenvWebpack๋ฅผ ํ†ตํ•ด ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํŒŒ์ผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋„๋ก ์„ค์ •

* feat: axios instance ๊ฐ์ฒด ์ƒ์„ฑ

baseUrl ์ง€์ •

* feat: react-query ๋ฐ devtools ์„ค์ • ์ถ”๊ฐ€

* chore: @apis path alias ์ถ”๊ฐ€

* refactor: theme ๋‚ด detail์— font-family ์ œ๊ฑฐ

* feat: Box ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: Carousel ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: Header ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: Tab ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: TransformBottomSheet ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: PlaceDetailCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: TravelogueTabContent ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: GoogleMapView ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* chore: re-export ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

* feat: ์ดˆ๊ธฐ ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ ๊ตฌํ˜„

* chore: .gitignore ๋‚ด .env.development, .env.production๋งŒ ์˜ค๋„๋ก ๋ณ€๊ฒฝ

* chore: @react-google-maps/api ์˜์กด์„ฑ ์ถ”๊ฐ€

* fix(Carousel): ์ด๋ฏธ์ง€๊ฐ€ ์ด๋™ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

max-width ๋Œ€์‹  transform ์†์„ฑ ์ถ”๊ฐ€

* [Feature] - codeowner ๋ฐ ์ž๋™ ํ• ๋‹น ์„ค์ • (#59)

* chore: codeowners ์„ค์ • ์ถ”๊ฐ€

* [Feature] - ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์„ค์ • ์ถ”๊ฐ€ (#58)

* chore: storybook ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

* chore: jest ๊ด€๋ จ ์˜์กด์„ฑ ๋ฐ script ์ถ”๊ฐ€

* chore: jest config ํŒŒ์ผ ๊ด€๋ จ ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: eslint ํŒŒ์ผ ๋‚ด jest plugin ์ถ”๊ฐ€

* [Feature] Storybook ๋ฐฐํฌ ์„ค์ • (#61)

* chore: chromatic ๋ฐฐํฌ ์„ค์ • ์ถ”๊ฐ€

* feat: TransformBottomSheet story ํŒŒ์ผ ์ถ”๊ฐ€

* chore: chromatic ci/cd ์„ค์ • ์ถ”๊ฐ€

* [Feature] - react-router-dom ์„ค์ •  (#71)

* chore: react-router-dom ์„ธํŒ…

* chore: createBrowserRouter ์ ์šฉ

* chore: @constants path alias ์ถ”๊ฐ€

* feat: AppLayout ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€

1. TravelogueDetailPage ๋‚ด margin-top ์ œ๊ฑฐ

2. AppLayout ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: router path ๊ด€๋ จ ์ƒ์ˆ˜ ์ถ”๊ฐ€

* refactor: router ์„ธํŒ… ๋ณ€๊ฒฝ

1. App ๋‚ด router router.tsx๋กœ ์ด๋™

2. router.tsx ๋‚ด AppLayout ์ถ”๊ฐ€ ๋ฐ router path ์„ค์ •

* chore: storybook-addon-remix-react-router ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: storybook ๋‚ด router addon ์„ค์ • ์ถ”๊ฐ€

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Feature] - ์„œ๋น„์Šค Foundation ์„ค์ • (#76)

* chore: styles ๋‚ด declare ํŒŒ์ผ๋“ค types ํด๋”๋กœ ์ด๋™

* chore: foundation ์ •์˜

1. color, spacing, typography์— ๋Œ€ํ•œ foundation ์ถ”๊ฐ€

2. global theme ๋ณ€๊ฒฝ

3. emotion.d.ts ๋‚ด declare theme ํƒ€์ž… ๋ณ€๊ฒฝ

* refactor: foundation ์ปดํฌ๋„ŒํŠธ ๋“ค์— ์ ์šฉ

* chore: stylelint ์ ์šฉ

* [Feature] - msw ์„ค์ • (#73)

* chore: msw ์˜์กด์„ฑ ์ถ”๊ฐ€

* fix: msw v2 ๋‚ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•œ ํด๋ฆฌํ•„ ์ฝ”๋“œ ์ถ”๊ฐ€

ReferenceError: TextEncoder is not defined ์—๋Ÿฌ ๋ฐœ์ƒ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ํด๋ฆฌํ•„ ์ฝ”๋“œ ์ถ”๊ฐ€

1. package.json ๋‚ด undici ์˜์กด์„ฑ ์ถ”๊ฐ€

2. jest.polyfills.js ๋‚ด ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

3. jest.config.js ๋‚ด ํด๋ฆฌํ•„ ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

* chore: @mocks ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

1. path alias ์ถ”๊ฐ€(webpack, tsconfig)

2. prettier import sort ๋‚ด mocks ์ถ”๊ฐ€

* chore: typescript ํ™˜๊ฒฝ์—์„œ jest api๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ • ์ถ”๊ฐ€

* chore: msw ๊ธฐ๋ณธ ์„ค์ • ์ถ”๊ฐ€

* chore: ๋ถˆํ•„์š”ํ•œ chromatic_publish ํŒŒ์ผ ์ œ๊ฑฐ

* chore: msw-storybook-addon ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: storybook ๋‚ด msw ์„ค์ • ์ถ”๊ฐ€

1. main.ts ๋‚ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ • ์ถ”๊ฐ€

2. preview.tsx ๋‚ด initialize & mswLoader ์„ค์ •, handler ์ถ”๊ฐ€

3. npx msw init public/ ๋ช…๋ น์–ด ์‹คํ–‰(mockServiceWorker.js & package.json ๋‚ด msw workerDirectory ์ถ”๊ฐ€

* [Feature] - ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„(์ง€๋‹ˆ) (#91)

* feat(assets): ํœด์ง€ํ†ต ์•„์ด์ฝ˜ ์ถ”๊ฐ€

* feat(Accordian): ์•„์ฝ”๋””์–ธ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Accordion): ์•„์ฝ”๋””์–ธ ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* feat(Button): ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Button): ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* test(Accordion): ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๋„ค์ด๋ฐ์„ ์˜์–ด๋กœ ์ˆ˜์ •

* feat(asset): asset ์ถ”๊ฐ€

* feat(Icon): ์•„์ด์ฝ˜ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Icon): Icon ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* feat(IconButton): IconButton ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(IconButton): IconButton ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* feat(Icon): svg๋“ค์— ๋Œ€ํ•œ json ํŒŒ์ผ ์ถ”๊ฐ€

* feat(Text): Text ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Text): Text ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* refactor(preview): ์Šคํ† ๋ฆฌ๋ถ root์— rootStyle ์ถ”๊ฐ€

* test(Text): Overview ์Šคํ† ๋ฆฌ ์ถ”๊ฐ€

* test(preview): ์Šคํ† ๋ฆฌ๋ถ ํ™˜๊ฒฝ root style ๋ณ€๊ฒฝ

1. preview.tsx ๋‚ด rootStyle ๋ณ€๊ฒฝ ํ›„ ๋‹ค๋ฅธ story๋“ค์— ์ ์šฉ

* refactor(Button): ButtonVariants import ์‹œ type ์ถ”๊ฐ€

* refactor(Text): ๋ณ€์ˆ˜ ๋‚ด์—์„œ export ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(Icon): type๋“ค type.ts๋กœ ๋ถ„๋ฆฌ

* refactor(Icon): import ๋ฐฉ์‹ ๋ณ€๊ฒฝ

* [Feature] - ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„(์‹œ๋ชจ) (#90)

* feat(Input): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(InputField): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* fix(tsconfig): ๊ฐœํ–‰์œผ๋กœ ์ธํ•œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* test(Input): ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* test(InputField): ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* refactor(InputContainer): ํŒŒ์ผ๋ช… ์ˆ˜์ • ๋ฐ count ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ

* feat(Textarea): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor(Textarea): props ๋ฐ css ์ˆ˜์ •

* test(Textarea): ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* refactor(Count): ๋„ค์ด๋ฐ ์ง๊ด€์ ์œผ๋กœ ์ˆ˜์ •

* refactor(Input): InputContainer๋ฅผ Input์œผ๋กœ ๋‹จ์ผํ™”

* refactor(Textarea): title ์ˆ˜์ •

* feat(BackDrop): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(asset): Tturi svg ์ถ”๊ฐ€

* refactor(BackDrop): position ์ˆ˜์ •

* feat(asset): close-button svg ์ถ”๊ฐ€

* feat(Button): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(ModalContainer): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(ModalContent): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(ModalFooter): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(ModalHeader): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(Modal): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Modal): ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* refactor(asset): close button ์‚ญ์ œ

* refactor: modalBottomSheet๋กœ ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(storybook): ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์„ ์œ„ํ•œ preview ์ˆ˜์ •, ๋ถˆํ•„์š”ํ•œ ์Šคํ† ๋ฆฌ๋ถ ํ…Œ์ŠคํŠธ ์‚ญ์ œ ๋ฐ ๋„ค์ด๋ฐ ์ˆ˜์ •

* feat(Container): ์—๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€

---------

Co-authored-by: jinyoung <[email protected]>

* [Feature] - ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„(๋ฆฌ๋ฒ„) (#89)

* feat: MultiImageUpload ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: ThumbnailUpload ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* fix: emotion css๋ฅผ styled๋กœ ์ˆ˜์ •

- storybook์—์„œ emotion css๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ emotion styled๋กœ ์ˆ˜์ •

* test: ThumnailUpload ์ปดํฌ๋„ŒํŠธ storybook ์ถ”๊ฐ€

* feat: MultiImageUpload ์ปดํฌ๋„ŒํŠธ ์ด๋ฏธ์ง€ ์‚ญ์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor: MultiImageUpload ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•จ์ˆ˜๋ช… ์ฝ”๋“œ ์ปจ๋ฒค์…˜์— ๋งž๊ฒŒ ์ˆ˜์ •

* feat: ThumbnailUpload ์ปดํฌ๋„ŒํŠธ ์ธ๋„ค์ผ ์ˆ˜์ • ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat: ThumbnailUploadButton์— gap ์ˆ˜์ •

* refactor: ThumbnailUpload ์ปดํฌ๋„ŒํŠธ์—์„œ ์ค‘๋ณต ์ œ๊ฑฐ

* refactor: ThumbnailUpload ์ปดํฌ๋„ŒํŠธ์—์„œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ๋‹จ์ˆœํ™”

* fix: MulitiImageUpload ์ปดํฌ๋„ŒํŠธ์—์„œ emotion css๋ฅผ emotion styled๋กœ ์ˆ˜์ •

- storybook์—์„œ emotion css ์ ์šฉ ๋˜์ง€ ์•Š๋Š” ์ด์Šˆ๋•Œ๋ฌธ์— ์ˆ˜์ •

* refactor: ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๋กœ์ง์„ useImageUpload๋กœ ๋ถ„๋ฆฌ

* test: MultiImageUpload ์ปดํฌ๋„ŒํŠธ storybook ์ถ”๊ฐ€

* fix: ThumbnailUpload ์ปดํฌ๋„ŒํŠธ storybook title ์ˆ˜์ •

* fix: MultiImageUpload ์ปดํฌ๋„ŒํŠธ storybook title ์ˆ˜์ •

* refactor: ThumbnailUpload ์ปดํฌ๋„ŒํŠธ storybook์—์„œ base64๋ฅผ mageUrl๋กœ ์ˆ˜์ •

-CORS ์ •์ฑ…๋•Œ๋ฌธ์— ์™ธ๋ถ€ URL์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ง์ ‘ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์•ˆ๋์—ˆ๋‹ค.
- ์ด ๋•Œ๋ฌธ์— imageUrl ๋Œ€์‹  base64๋ฅผ ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค
- base64 ๊ฐ’์ด ๋„ˆ๋ฌด ๊ธธ๋‹ค
- ๋•Œ๋ฌธ์— ๋ฌด๋ฃŒ CORS ํ”„๋ก์‹œ ์„œ๋น„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ imageUrl์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ˆ˜์ •

* feat: MultiImageUpload ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฏธ์ง€ ๋ Œ๋”๋ง ๋ถ€๋ถ„์— ์Šคํฌ๋กค ์ถ”๊ฐ€

* test: MultiImageUpload ์ปดํฌ๋„ŒํŠธ storybook์— ์ด๋ฏธ์ง€ ๋งŽ์ด ์ฒจ๋ถ€ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€

* refactor: MultiImageUpload ์ปดํฌ๋„ŒํŠธ ์‚ญ์ œ ๋ฒ„ํŠผ์— svg ์‚ฌ์šฉ

* refactor: MultiImageUpload ์ปดํฌ๋„ŒํŠธ์—์„œ styled ์ปดํฌ๋„ŒํŠธ๋ช… ์ˆ˜์ •

* feat: useDragScroll hook ๊ตฌํ˜„

* feat: MultiImageUpload ์ปดํฌ๋„ŒํŠธ์— ๋“œ๋ž˜๊ทธ ์Šคํฌ๋กค ๊ธฐ๋Šฅ ์ถ”๊ฐ€

* feat: MultiImageUpload ์ปดํฌ๋„ŒํŠธ์— y์ถ• ์Šคํฌ๋กค hidden ์ถ”๊ฐ€

* refactor: MultiImageUpload ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์ง„ ์ถ”๊ฐ€ ๋ฒ„ํŠผ UI ์ˆ˜์ •

---------

Co-authored-by: jinyoung <[email protected]>

* [Feature] - ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#115)

* feat: types path alias ์ถ”๊ฐ€

* refactor(AccordionRoot): ๋‹ค๋ฅธ attributes๋“ค๋„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋ณ€๊ฒฝ

* fix(preview): ์Šคํ† ๋ฆฌ๋ถ ์—ด๋ฆฌ์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

div ํƒœ๊ทธ ์ถ”๊ฐ€

* chore: type, queries, hooks์— ๋Œ€ํ•œ type alias ์ถ”๊ฐ€

* feat: DayContent ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor(GoogleMapView): LoadScript ์™ธ๋ถ€๋กœ ๋ถ„๋ฆฌ

1. GoogleMapView์—์„œ LoadScript ์ œ๊ฑฐ

2. GoogleMapLoadScript ์ถ”๊ฐ€

* feat(GoogleSearchPopup): GoogleSearchPopup ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor(ModalBottomSheet): currentY ๊ฐ’ open์‹œ 0์ด ๋˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(ModalBottomSheet): stylelint ์ ์šฉ

* refactor(MultiImageUpload): useImageUpload ๋ฐ˜ํ™˜ ๊ฐ’์„ ์™ธ๋ถ€์—์„œ ์ฃผ์ž… ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

* feat(PageInfo): PageInfo ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(PageInfo): PageInfo ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* chore: useDragScroll, useImageUpload ๊ฒฝ๋กœ ๋ณ€๊ฒฝ

hooks์— ์œ„์น˜ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(ThumbnailUpload): useImageUpload ๋ฐ˜ํ™˜ ๊ฐ’์„ ์™ธ๋ถ€์—์„œ ์ฃผ์ž… ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

* feat(TravelogueMultiImgaeUpload): TravelogueMultiImgaeUpload ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: register route path ์ถ”๊ฐ€

* feat(useTravelDays): useTravelDays hook ๊ตฌํ˜„

* feat: travelogue ๊ณตํ†ต ํƒ€์ž…๋“ค ์ถ”๊ฐ€

* feat: usePostTrevelogue ๊ตฌํ˜„

* feat: usePostUploadImages ๊ตฌํ˜„

* chore: reexport ์ถ”๊ฐ€

* feat: ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ๊ธฐ๋Šฅ ๊ตฌํ˜„

1. router์— ์ถ”๊ฐ€

2. ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ํŽ˜์ด์ง€ ์ถ”๊ฐ€

* feat: ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ์™„๋ฃŒ ์‹œ ํ•ด๋‹น ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€

* [Feature] - ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#80)

* chore(stylelint): properties ์ถ”๊ฐ€

* refactor(style): ์Šคํƒ€์ผ๋ฆฐํŠธ ์ ์šฉ

* feat(theme): white ์ปฌ๋Ÿฌ ์ถ”๊ฐ€

* refactor(Header): ์žฌ์‚ฌ์šฉ์„ฑ์„ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ •

* refactor(style): Header align-items ์ถ”๊ฐ€

* feat(assets): Tturi webp asset ์ถ”๊ฐ€

* feat(Login): ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* chore: dev ์‹คํ–‰์„ ์œ„ํ•œ dotenv-webpack ์„ค์น˜

* feat(assets): kakao symbol ์ถ”๊ฐ€

* feat(theme): yellow color ์ถ”๊ฐ€

* feat(LoginPage): ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ ๋ฐ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ UI ์ถ”๊ฐ€ ๊ตฌํ˜„

* feat(LoginPage): ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๊ตฌํ˜„

* chore(webpack.common.js): publicPath ์ถ”๊ฐ€

* feat: IconButton ๊ตฌํ˜„

* refactor(Header): Header ๋‚ด content๋ฅผ ๋‚ด๋ถ€์— ๋„ฃ๋„๋ก ๋ณ€๊ฒฝ

* refactor(ExcitedTturi): tturi์—์„œ ๋„ค์ด๋ฐ ์ˆ˜์ •

* feat(constants): ROUTE_PATHS ์ถ”๊ฐ€

* refactor(LoginPage): ๋ถˆํ•„์š”ํ•œ ์ฃผ์„ ์‚ญ์ œ ๋ฐ ํ•ธ๋“ค๋Ÿฌ ๋„ค์ด๋ฐ ์ˆ˜์ •

* feat(KakaoCallbackPage): ํŽ˜์ด์ง€ ๊ตฌํ˜„

* feat(router): kakaoCallbackPage ์ถ”๊ฐ€

* feat(App): useContext ์ถ”๊ฐ€

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>
Co-authored-by: jinyoung <[email protected]>

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#125)

* chore: react-datepicker ์ž„์‹œ๋กœ ์‚ฌ์šฉ(๋ฐ๋ชจ๋ฐ์ด๋•Œ ๋น ๋ฅด๊ฒŒ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•จ)

* chore: css-loader, style-loader ์ถ”๊ฐ€

๋ฐ๋ชจ๋ฐ์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” date-picker๋ฅผ ์œ„ํ•ด ์ž„์‹œ๋กœ ์„ค์น˜

* feat(DateRangePicker): ์ž„์‹œ๋กœ ์‚ฌ์šฉํ•  DateRangePicker ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor(Input): maxCount, count optional๋กœ ๋ณ€๊ฒฝ

* chore(main): datepicker css ์ถ”๊ฐ€

* refactor: Place ๋‚ด name์„ placeName์œผ๋กœ ๋ณ€๊ฒฝ

* refactor(useTravelDays): onAddDay์— useCallback ์ถ”๊ฐ€

* feat(usePostTravelPlan): ์—ฌํ–‰ ๊ณ„ํš post ์š”์ฒญ hook ๊ตฌํ˜„

* feat(TravelogueRegisterPage): ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๊ตฌํ˜„

* [Feature] - ๋ฉ”์ธ ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#78)

* feat: AvatarCircle ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test: AvatarCircle ์ปดํฌ๋„ŒํŠธ storybook ์ถ”๊ฐ€

* feat: TravelogueCard ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test: TravelogueCard ์ปดํฌ๋„ŒํŠธ storybook ์ถ”๊ฐ€

* feat: MainPage ๊ตฌํ˜„

* refactor: AvatarCircle ์ปดํฌ๋„ŒํŠธ useAvatar๊ฐ€ undefined์ผ๋•Œ๋„ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€ ๋ณด์ด๋„๋ก ์ˆ˜์ •

* feat: TravelCard ์ปดํฌ๋„ŒํŠธ์—์„œ likes ๊ธฐ๋ณธ๊ฐ’ 0์œผ๋กœ ์„ค์ •

* feat: useIntersectionObserver ํ›… ๊ตฌํ˜„

* feat: useInfiniteTravelogues ๊ตฌํ˜„

- 5๊ฐœ์”ฉ fetchํ•ด์˜ต๋‹ˆ๋‹ค.

* refactor: ๋ฉ”์ธํŽ˜์ด์ง€์—์„œ useInfiniteTravelogues ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

* feat: Drawer ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: Header ์ปดํฌ๋„ŒํŠธ์— Drawer ์ถ”๊ฐ€

* test: Drawer storybook ์ถ”๊ฐ€

* feat: Drawer ์ปดํฌ๋„ŒํŠธ style ์ˆ˜์ •

* refactor: ์ž˜๋ชป๋œ image url ๋‹ค๋ฃจ๋Š” ๋ถ€๋ถ„ useImageError ํ›…์œผ๋กœ ๋ถ„๋ฆฌ

* feat: TravelCard ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž˜๋ชป๋œ image url ํ•ธ๋“ค ์ถ”๊ฐ€

* test: TravelogueCard ์ปดํฌ๋„ŒํŠธ strorybook์— ์œ ์š”ํ•˜์ง€ ์•Š์€ ์ธ๋„ค์ผ ์ผ€์ด์Šค ์ถ”๊ฐ€

---------

Co-authored-by: jinyoung <[email protected]>

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ์กฐํšŒ ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#127)

* chore: ์—…๋ฐ์ดํŠธ๋œ ๋‹ค๋ฅธ ํŒŒ์ผ๊ณผ ๋™๊ธฐํ™”

* feat(TravelPlansTabContent): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(TravelPlansDetail): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor(TravelogueDetailPage): ํƒ€์ž… ๋ถ„๋ฆฌ ๋ฐ TransformBottomSheet props ์ˆ˜์ •์— ๋”ฐ๋ฅธ ๋ณ€๊ฒฝ

* refactor: ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ • ๋ฐ ๋ถˆ ํ•„์š”ํ•œ ์ฝ”๋“œ ์‚ญ์ œ

Co-authored-by: choi river <[email protected]>
Co-authored-by: simorimi <[email protected]>

* refactor: ์Šคํƒ€์ผ๋ง ์กฐ์ • ๋ฐ stylelint์— ๋งž๊ฒŒ ์ˆœ์„œ ์ˆ˜์ •

* refactor(storybook): decorator ์ˆ˜์ •

* chore(createPathElement): ์„ค์ •

* [Feature] - 2์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ์ง„ํ–‰ (#141)

* refactor: ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ • ๋ฐ ๋ถˆ ํ•„์š”ํ•œ ์ฝ”๋“œ ์‚ญ์ œ

Co-authored-by: choi river <[email protected]>
Co-authored-by: simorimi <[email protected]>

* refactor: ์Šคํƒ€์ผ๋ง ์กฐ์ • ๋ฐ stylelint์— ๋งž๊ฒŒ ์ˆœ์„œ ์ˆ˜์ •

* refactor(storybook): decorator ์ˆ˜์ •

* chore(createPathElement): ์„ค์ •

* fix(router): router ์ˆ˜์ •

1. travelPlans url์— TravelPlansDetailPage ์ถ”๊ฐ€

2. travelPlansRegister url์— TravelPlanRegisterPage ์ถ”๊ฐ€

* fix(Header): title style ๋ณ€๊ฒฝ

align-items center ์ถ”๊ฐ€

* fix(Drawer): DrawerHeader ์Šคํƒ€์ผ ์กฐ์ •

align-items center ์ถ”๊ฐ€

* fix(TravelogueCard): ์นด๋“œ ๋””์ž์ธ ์‹œ์•ˆ ๋ณ€๊ฒฝ

1. CardHeader๊ฐ€ ๋ฐ‘์œผ๋กœ ๊ฐ€๋„๋ก ๋ณ€๊ฒฝ

2. Layout์˜ animation ์ œ๊ฑฐ ํ›„ border ๊ด€๋ จ ์Šคํƒ€์ผ ์ถ”๊ฐ€

* fix(TravelPlansTabContent): name์„ placeName์œผ๋กœ ๋ณ€๊ฒฝ

* fix: ROUTE_PATHS ์ˆ˜์ •

1. travelPlans ์ถ”๊ฐ€

2. travelPlansRegister์˜ url endpoint ๋ณ€๊ฒฝ

* refactor(TravelPlansTabContent): stylelint ์ ์šฉ

* refactor(TravelogueDetailPage): ๋ถˆํ•„์š”ํ•œ import ์ œ๊ฑฐ

* test(MultiImageUpload): storybook ์˜ค๋ฅ˜ ์ˆ˜์ •

* test(ThumbnailUpload): ThumbnailUpload ์Šคํ† ๋ฆฌ๋ถ ์ˆ˜์ •

* refactor(MainPage): stylelint ์ ์šฉ

* fix(TravelPlansDetail): ์—ฌํ–‰ ๊ณ„ํš api ์˜ค๋ฅ˜ ์ˆ˜์ •

1. headers ์ถ”๊ฐ€(Authorization)

2. queryKey ๋ณ€๊ฒฝ

3. useGetTravelPlan ๋ถ„๋ฆฌ

* fix(Header): ํ—ค๋” ๊ด€๋ จ ์˜ค๋ฅ˜ ์ˆ˜์ •

1. ๋กœ๊ทธ์ธ ๋‚ด click ์•ก์…˜ ์‹œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋„๋ก ์ˆ˜์ •

2. access token ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋กœ๊ทธ์ธ/๋กœ๊ทธ์•„์›ƒ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋ณ€๊ฒฝ

3. HeaderTitle ์ปดํฌ๋„ŒํŠธ ์ œ๊ฑฐ

* chore: type ๊ด€๋ จ import sort ์ถ”๊ฐ€

* fix: TravelPlanRegisterPage navigate url ์ˆ˜์ •

* feat(asset): svg-icons.json ๋‚ด asset ์ถ”๊ฐ€

* feat: MainPage ๋‚ด FloatingButton ์ถ”๊ฐ€

* refactor(useGetTravelPlan): queryFn ํ˜•ํƒœ ๋ณ€๊ฒฝ

* fix(TravelogueDetailPage): margin-top ๋ณ€๊ฒฝ

* fix(TransformBottomSheet): text-align center ๋ณ€๊ฒฝ

* refactor: declare file ๊ด€๋ฆฌ

1. ๋ถˆํ•„์š”ํ•œ emotion.d.ts ํŒŒ์ผ ์ œ๊ฑฐ

2. style.d.ts์— ๋ชจ๋“  declare type ์ถ”๊ฐ€

* chore: context path alias ์„ค์ • ์ถ”๊ฐ€

* chore: jest ๋‚ด moduleNameMapper ์ˆ˜์ •

* refactor(AvatarCircle): userAvatar props ๋ณ€๊ฒฝ

profileImageUrl๋กœ ๋ณ€๊ฒฝ

* test(AvatarCircle): argTypes(userAvatar)๋ฅผ profileImageUrl๋กœ ๋ณ€๊ฒฝ

* refactor: App ๋‚ด Context๋“ค UserProvider๋กœ ๋ถ„๋ฆฌ

* refactor: useUser hook ๋ถ„๋ฆฌ

* style: ๋ถˆํ•„์š”ํ•œ ํŒŒ์ผ ์ œ๊ฑฐ

* fix(Header): ๋กœ๊ทธ์ธ ํ™”๋ฉด์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ์•„์ด์ฝ˜์˜ ์ƒ‰์ด ์ž˜๋ชป๋œ ์ด์Šˆ ํ•ด๊ฒฐ

* refactor(TravelPlansDetailPage): Context import ๊ฒฝ๋กœ ๋ฐ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ

* refactor(Container): stylelint ์ ์šฉ

* refactor(MainPage): TravelogueCard ์ปดํฌ๋„ŒํŠธ ๋‚ด key prop ์ถ”๊ฐ€

* fix(LoginPage): ๋šœ๋ฆฌ ์ด๋ฏธ์ง€๊ฐ€ ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ ๋ณด์ด์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

webp์—์„œ gif ํŒŒ์ผ๋กœ ๋ณ€๊ฒฝ

* refactor(KakaoCallbackPage): UseSetUseContext import ๊ฒฝ๋กœ ๋ฐ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ

* refactor(TravelogueCard): AvatarCircle prop name ๋ณ€๊ฒฝ

* refactor(TravelPlansDetail): stylelint ์ ์šฉ

* refactor(PlaceDetailCard): ์ด๋ฏธ์ง€๊ฐ€ 1๊ฐœ ์ผ๋•Œ ์บ๋Ÿฌ์…€์ด ์•„๋‹Œ ์ผ๋ฐ˜ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋„๋ก ๋ณ€๊ฒฝ

* refactor(TravelogueDetailPage): TitleContainer ์Šคํƒ€์ผ ๋ณ€๊ฒฝ

* refactor(TravelogueDetailPage): font title์ด ์•„๋‹Œ subtitle๋กœ ๋ณ€๊ฒฝ

* feat: favicon ์ถ”๊ฐ€

* chore: storybook path alias ์ถ”๊ฐ€(contexts)

* chore: ๋ณ€๊ฒฝ์‚ฌํ•ญ ๋ฐ˜์˜

* refactor: queries ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ ๋ณ€๊ฒฝ

* chore: ๋ถˆํ•„์š”ํ•œ console.log ์ œ๊ฑฐ

* refactor(useImageUpload): ํ•ด๋‹น hook ์ œ๊ฑฐ

local state๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ๋ฐ›์€ url์„ ์ปดํฌ๋„ŒํŠธ์— ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ

* refactor(TravelogueDetailPage): ๋ฆฌ์•กํŠธ ์ฟผ๋ฆฌ hook ๋กœ์ง ๋ถ„๋ฆฌ

useGetTravelogue๋กœ ๋ถ„๋ฆฌ

---------

Co-authored-by: choi river <[email protected]>
Co-authored-by: simorimi <[email protected]>

* chore: chromatic ๋ฐฐํฌ yml ํŒŒ์ผ ์ถ”๊ฐ€ (#117)

* [Feature] - CI ์„ค์ • (#66)

* fix: __tests__ ๋‚ด jest ํƒ€์ž… ์—๋Ÿฌ ํ•ด๊ฒฐ

* chore: styled ํŒŒ์ผ ๋‚ด stylelint ์ ์šฉ

* chore: ํ”„๋ก ํŠธ์—”๋“œ ci ์„ค์ • github actions ์ถ”๊ฐ€

* chore: jest-junit ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: jest.config.js ๋‚ด reporters ์˜ต์…˜ ์ถ”๊ฐ€

* chore: ci ์Šคํฌ๋ฆฝํŠธ ๋‚ด check ์ฝ”๋ฉ˜ํŠธ ์ถ”๊ฐ€

* feat: ํ†ต๊ณผ ํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

* test: ์˜ˆ์ œ ํ…Œ์ŠคํŠธ ์ œ๊ฑฐ

* chore: jest ์„ค์ • ๋‚ด --passWithNoTests config ์ถ”๊ฐ€

* [Feature] - 3์ฃผ์ฐจ ์Šคํ”„๋ฆฐํŠธ ๋ฆฌํŒฉํ† ๋ง (#145)

* feat: ์•„์ฝ”๋””์–ธ toggle trigger๋ถ€๋ถ„์„ ํ™•์žฅ

* feat: FloatingButton์ด ๊ฐ€๋ ค์ง€์ง€ ์•Š๊ฒŒ z-index ์ถ”๊ฐ€

* feat: description์— ํฌํ•จ๋œ ๊ฐœํ–‰ ๋ฌธ์ž ์ ์šฉ๋˜๋„๋ก ์ˆ˜์ •

* feat: tab ์ปดํฌ๋„ŒํŠธ์—์„œ 3์ผ ์ด์ƒ์ธ ๊ฒฝ์šฐ ๋งˆ์ง€๋ง‰ tab์€ ๋ฐ˜๋งŒ ๋ณด์ด๋„๋ก ๊ตฌํ˜„

* fix: ์ด๋ฏธ์ง€์™€ ์ปจํ…Œ์ด๋„ˆ border๊ฐ€ ๊ฐ๊ฐ ๋ณด์ด๋Š” ๋ถ€๋ถ„ ์ˆ˜์ •

* chore: yarn.lock ์—…๋ฐ์ดํŠธ

* fix: ci ์—๋Ÿฌ ํ•ด๊ฒฐ (#150)

install --frozen-lockfile ์ œ๊ฑฐ

* [Feature] - sentry ์„ธํŒ…ํ•˜๊ธฐ (#168)

* chore: sentry/react ์„ค์น˜

* feat: ApiError ๊ฐ์ฒด ๊ตฌํ˜„

* feat: sentry ์ดˆ๊ธฐ ์„ค์ •

* fix: ์ž˜๋ชป๋œ name ์ˆ˜์ •

* fix: ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜ import ์ˆ˜์ •

* [Feature] - 2์ฐจ ์Šคํ”„๋ฆฐํŠธ ๋ฆฌํŒฉํ† ๋ง (#164)

* refactor(useGetTravelogue): queryFn ์ˆ˜์ •

* chore: datepicker ์ถ”๊ฐ€์— ๋”ฐ๋ฅธ ๋ณ€๊ฒฝ

* fix(globalStyle): ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ์ฃผ์†Œ์ฐฝ์ด ์ „์ฒด ํ™”๋ฉด ํฌ๊ธฐ์— ํฌํ•จ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(Header): ๋ถˆ ํ•„์š”ํ•œ z-index ์ œ๊ฑฐ

* fix(ModalBottomSheet): useBottomSheet ๋ถ„๋ฆฌ ๋ฐ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ์ž‘๋™ํ•˜๋„๋ก ์ˆ˜์ •

* refactor: z-index ์ถ”๊ฐ€

* refactor(useBottomSheet): ์ƒ์ˆ˜ํ™”

* [Feature] - ์ „ํ™˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#146)

* fix(useGetTravelogue): merge ๊ณผ์ •์—์„œ queryFn ์‚ฌ๋ผ์ง„ ์˜ค๋ฅ˜ ์ˆ˜์ •

* fix(App): ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ œ๋Œ€๋กœ ๋ฐ›์ง€ ๋ชปํ•˜๋Š” ์˜ค๋ฅ˜ ์ˆ˜์ •

App ์ด์™ธ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ ์œ ์ € ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค์ง€ ๋ชปํ•˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* fix(useGetTravelogue): ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๊ฐ€ ๋‹ฌ๋ผ ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ ๋ฐœ์ƒ ํ•ด๊ฒฐ

data return ํ˜•ํƒœ ๋ณ€๊ฒฝ

* refactor(Header): useContext๋กœ ์œ ์ € ์ •๋ณด๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์ด ์•„๋‹Œ useUser hook์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ

* feat: ์—ฌํ–‰๊ธฐ - ์—ฌํ–‰ ๊ณ„ํš ๋ณ€ํ™˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„

1. TravelogueProvider ๊ตฌํ˜„

2. App ๋‚ด TravelogueProvider ์ถ”๊ฐ€

3. TransformBottomSheet ๋‚ด onTransform prop ์ถ”๊ฐ€

4. TravelogueDetailPage ๋‚ด onTransform ๋กœ์ง ์ถ”๊ฐ€

5. TravelPlanRegisterPage ๋‚ด travelogue ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

6. useTravelDays ๋‚ด days ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

* feat: ์—ฌํ–‰๊ณ„ํš - ์—ฌํ–‰๊ธฐ ์ „ํ™˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor: ์—ฌํ–‰ ๊ณ„ํš - ์—ฌํ–‰๊ธฐ ๋ณ€ํ™˜ ์‹œ ๊ณตํ†ต๋˜๋Š” ๋ถ€๋ถ„์„ TransformDetail๋กœ ํ†ต์ผ

* refactor: ์—ฌํ–‰ ๊ณ„ํš ๋ณ€ํ™˜ ์‹œ title ์ œ๊ฑฐ

๋ณ€ํ™˜ ์‹œ title์ด ์—†๋„๋ก ๋ณ€๊ฒฝ

* refactor(TravelogueProvider): import ๋‚ด type ์ถ”๊ฐ€

* refactor: import ๋‚ด type ์ถ”๊ฐ€

* refactor(TravelPlanDetailPage): ์ปดํฌ๋„ŒํŠธ ๋ช… ๋ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ณ€๊ฒฝ

1. TravelPlansDetail์—์„œ travelPlanDetail๋กœ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ณ€๊ฒฝ

2. TravelPlanDetailPage๋กœ ์ปดํฌ๋„ŒํŠธ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ

3. ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋“ค์— ๋ฐ˜์˜

* refactor(TravelTransformDetailProvider): ์—ฌํ–‰ ์ „ํ™˜ ์ •๋ณด ๋ฐ์ดํ„ฐ๋ฅผ TravelTransformDetail๋กœ ๋ณ€๊ฒฝ

1. type์„ TravelTransformPlaces์™€ TravelTransformDetail๋กœ ๋ณ€๊ฒฝ

2. TravelTransformDetailProvider๋กœ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ

* refactor: travelogue ํƒ€์ž… ํŒŒ์ผ ๋‚ด์—์„œ travelTransform์œผ๋กœ ๋ถ„๋ฆฌ

1. TravelTransformPlaces์™€ TravelTransformDetail ํƒ€์ž… ํŒŒ์ผ ๋ถ„๋ฆฌ

2. ๋ณ€๊ฒฝ ์‚ฌํ•ญ ์ ์šฉ

* chore: utils path alias ์ถ”๊ฐ€

* refactor: onTransformTravelDetail context hook ๋‚ด๋ถ€๋กœ ์ด๋™

* [Feature] - ์ธ๊ฐ€ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€ (#176)

* refactor(ApiError): Error ์ŠคํƒํŠธ๋ ˆ์ด์Šค ์ˆ˜์ •

AxiosError๊ฐ€ ์•„๋‹Œ custom name์ด ๋“ค์–ด๊ฐ€๋„๋ก ๋ณ€๊ฒฝ

* feat: ์ „์—ญ axios interceptor ์„ค์ • ์ถ”๊ฐ€

1. request ์ „ accessToken ํ™•์ธ ์ฒ˜๋ฆฌ ๋ฐ authorization header ๋‚ด access token ์ถ”๊ฐ€

2. APIError ๋ฐœ์ƒ ์‹œ sentry ์ŠคํƒํŠธ๋ ˆ์ด์„œ ์ถ”๊ฐ€

3. AxiosError๊ฐ€ ์•„๋‹Œ APIError๋ฅผ throw

* feat(TravelPlanRegisterPage): ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋‚ด ์ธ๊ฐ€ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

์•ก์„ธ์Šค ํ† ํฐ์ด ์—†๋‹ค๋ฉด login ํŽ˜์ด์ง€๋กœ redirect

* feat(TravelogueRegisterPage): ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋‚ด ์ธ๊ฐ€ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

์•ก์„ธ์Šค ํ† ํฐ์ด ์—†๋‹ค๋ฉด login ํŽ˜์ด์ง€๋กœ redirect

* refactor(main): sentry init ์„ค์ • ๋ณ€๊ฒฝ

* refactor(useGetTravelPlan): accessToken ์ฒ˜๋ฆฌ ๋กœ์ง ์ œ๊ฑฐ

* feat(usePostUploadImages): ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ์— ๋Œ€ํ•œ ์ธ๊ฐ€์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* refactor(interceptor): ErrorResponse์— ๋Œ€ํ•œํƒ€์ž… ์ถ”๊ฐ€

* feat(usePostTravelPlan): ์—ฌํ–‰ ๊ณ„ํš ์ถ”๊ฐ€์— ๋Œ€ํ•œ ์ธ๊ฐ€ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* feat(usePostTravelogue): ์—ฌํ–‰๊ธฐ ์ถ”๊ฐ€์— ๋Œ€ํ•œ ์ธ๊ฐ€ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* refactor(interceptor): import type ๋ณ€๊ฒฝ

* refactor: error response๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ

post query ๋‚ด cors ์—๋Ÿฌ์˜ ๊ฒฝ์šฐ error response๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•œ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ์œ„ํ•ด union ํƒ€์ž…์œผ๋กœ ์„ค์ •

* [Feature] - ์ƒ์ˆ˜ํ™” ์ž‘์—… ์ง„ํ–‰ (#188)

* refactor: route path ์ƒ์ˆ˜ํ™” ์ถ”๊ฐ€

1. ์—ฌํ–‰ ๊ณ„ํš, ์—ฌํ–‰๊ธฐ์— ๋Œ€ํ•œ route path ํ˜•ํƒœ ๋ณ€๊ฒฝ(optional ํ˜•ํƒœ๋กœ id๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜ ํ˜•ํƒœ)

2. navigate ํ•จ์ˆ˜ ๋‚ด ํ•˜๋“œ ์ฝ”๋”ฉ ๋œ url ๊ฐ’ ์ƒ์ˆ˜ํ™”

3. ROUTE_PATHS_MAP์œผ๋กœ ๋ณ€๊ฒฝ

* refactor: storage key ์ƒ์ˆ˜ํ™”

* refactor: api endpoint ์ƒ์ˆ˜ํ™”

* refactor: status code ๊ด€๋ จ map(record) constants ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™

* refactor: ์ฟผ๋ฆฌํ‚ค ์ƒ์ˆ˜ํ™”

* refactor: api endpoint ๋‚ด detail ๋„ค์ด๋ฐ ๋น ์ง„ ๋ถ€๋ถ„ ์ถ”๊ฐ€

* refactor: ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ƒ์ˆ˜ํ™”

* [Feature] - ํƒ€์ž… ๊ตฌ์กฐ ๋ณ€๊ฒฝ (#191)

* refactor: ํƒ€์ž… ๊ตฌ์กฐ ๋ณ€๊ฒฝ

1. travelogue, travelplan, traveltransformdetail์— ๋Œ€ํ•œ ํƒ€์ž…์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ

2. ๋ณ€๊ฒฝ ์‚ฌํ•ญ ์ ์šฉ(useTravelogueDays, useTraveloguePlanDays ๋ถ„๋ฆฌ)

3. DayContent ์ œ๊ฑฐ ํ›„ TravelogueDayAccordion, TravelPlanDayAccordion๊ฐ๊ฐ ์ถ”๊ฐ€

* fix: ์ถฉ๋Œ ๋‚œ ๋ถ€๋ถ„ ์ˆ˜์ •

* refactor: DayAccordion๋“ค์— ๋Œ€ํ•œ interface ๋ถ„๋ฆฌ

๊ฐ๊ฐ TravelPlanDayAccordionProps๊ณผ TravelPlanDayAccordionProps๋กœ ๋ถ„๋ฆฌ

* [Feature] - ์—ฌํ–‰๊ธฐ ๋ฌดํ•œ ์Šคํฌ๋กค ๊ด€๋ จ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ (#166)

* refactor(prettier): queries import order ์ˆ˜์ •

* fix(jest.config.js): msw๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

setupFilesAfterEnv ๋‚ด jest-setup.ts ์ถ”๊ฐ€

* test(mainPage): ์—ฌํ–‰๊ธฐ ๋ฌดํ•œ ์Šคํฌ๋กค ํ…Œ์ŠคํŠธ ๋กœ์ง ์ถ”๊ฐ€

1. ๋ฌดํ•œ์Šคํฌ๋กค ๊ด€๋ จ ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

2. ์—ฌํ–‰๊ธฐ mock ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

3. useInfiniteTravelogue๋ฅผ renderHook์œผ๋กœ wrappingํ•œ hook ์ถ”๊ฐ€(createInfiniteTravelogueHook)

4. ํ…Œ์ŠคํŠธ ๋กœ์ง ์ถ”๊ฐ€

* fix(useGetTravelogue): queryFn ๋ณ€๊ฒฝ

* [Feature] - ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#200)

* fix: ์—ฌํ–‰ ์ „ํ™˜ ํ›„ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ ๋‹ค์‹œ ๋“ฑ๋ก ํŽ˜์ด์ง€๋กœ ์ ‘๊ทผ ์‹œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#207)

ํŽ˜์ด์ง€๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด transformDetail๋ฅผ null๋กœ ๋ณ€๊ฒฝ

* [Fix] - ๋“ฑ๋ก ํŽ˜์ด์ง€์—์„œ ์ œ๋ชฉ๊ณผ ์—ฌํ–‰ ์žฅ์†Œ ์„ค๋ช…๋ž€ ํ•œ๊ธ€ ์ž…๋ ฅ์‹œ ์ œํ•œ ๊ธธ์ด๋ณด๋‹ค 1์ž ๋” ์ž…๋ ฅ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#210)

* fix(TravelogueRegisterPage): ํ•œ๊ธ€ ์ž…๋ ฅ์‹œ 21์ž๊นŒ์ง€ ์ž…๋ ฅ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* fix(TravelPlanRegisterPage): ํ•œ๊ธ€ ์ž…๋ ฅ์‹œ 21์ž๊นŒ์ง€ ์ž…๋ ฅ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* fix(useTravelogueDays): ์žฅ์†Œ ์„ค๋ช…๋ž€ ํ•œ๊ธ€ ์ž…๋ ฅ์‹œ 301์ž๊นŒ์ง€ ์ž…๋ ฅ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* fix(useTravelPlanDays): ์žฅ์†Œ ์„ค๋ช…๋ž€ ํ•œ๊ธ€ ์ž…๋ ฅ์‹œ 301์ž๊นŒ์ง€ ์ž…๋ ฅ๋˜๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* [Feature] - Login ๋ช…์„ธ ๋ณ€๊ฒฝ (#181)

* refactor(KakaoCallbackPage): http method๋ฅผ get์œผ๋กœ ๋ณ€๊ฒฝ

* refactor(KakaoCallbackPage): encoding๋œ redirect-uri params์— ์ถ”๊ฐ€

* fix: ๋กœ๊ทธ์ธ ๋ช…์„ธ ๋ณ€๊ฒฝ

1. http method post๋กœ ๋ณ€๊ฒฝ

2. params์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ url๋‚ด code ๋ฐ redirectUri ์ถ”๊ฐ€

* fix: ci ์‹คํŒจ ํ•˜๋Š” ์›์ธ ์ˆ˜์ •

1. api endpoint map ๋‚ด loginOauth ์ˆ˜์ •

2. KakaoCallbackPage ๋‚ด ๋ฐ˜์˜

---------

Co-authored-by: simhorim <[email protected]>

* [Feature] - ๋ฉ”์ธํŽ˜์ด์ง€ skeleton ์ž‘์—… (#221)

* feat: TravelogueCardSkeleton ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test: TravelogueCardSkeleton storybook ์ถ”๊ฐ€

* feat: ๋ฉ”์ธ ํŽ˜์ด์ง€์— skeleton UI ์ถ”๊ฐ€

* feat: ์Šค์ผˆ๋ ˆํ†ค ์ปดํฌ๋„ŒํŠธ์— key ์ถ”๊ฐ€

* fix: styled ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ์ปจ๋ฒค์…˜์— ๋งž๋„๋ก ์ˆ˜์ •

* fix: styled ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ์ปจ๋ฒค์…˜์— ๋งž๋„๋ก ์ˆ˜์ •

* [Feature] - Drawer๊ฐ€ ์—ด๋ ค์ ธ์žˆ๋Š” ๊ฒฝ์šฐ ํ™”๋ฉด ์Šคํฌ๋กค ์•ˆ๋˜๋„๋ก ์ˆ˜์ • (#222)

* feat: Drawer๊ฐ€ ์—ด๋ ค์ ธ์žˆ๋Š” ๊ฒฝ์šฐ ํ™”๋ฉด ์Šคํฌ๋กค ์•ˆ๋˜๋„๋ก ์ˆ˜์ •

* refactor: Drawer์—์„œ DrawerProvider๋ฅผ contexts๋กœ ๋ถ„๋ฆฌ

* refactor: useModalControl ํ›…์„ ์ด์šฉํ•˜์—ฌ ๋ฆฌํŒฉํ† ๋ง

* [Feature] - user ์ปจํ…์ŠคํŠธ์— access token๋งŒ ๋‹ด๋„๋ก ์ˆ˜์ • & ๋กœ๊ทธ์ธ/๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ์ˆ˜์ • (#224)

* feat: useUserProfile ํ›… ๊ตฌํ˜„

Co-Authored-By: eunjungL <[email protected]>

* refactor: UserProvider์— accessToken๋งŒ ์ €์žฅํ•˜๋„๋ก ์ˆ˜์ •

* feat: ์นด์นด์˜ค ๋กœ๊ทธ์ธ์‹œ accessToken๋งŒ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•˜๋„๋ก ์ˆ˜์ •

* fix: Header์˜ Drawer์— ๋กœ๊ทธ์ธ/๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ๋ณ€ํ•˜๋„๋ก ์ˆ˜์ •

* feat: ๋กœ๊ทธ์•„์›ƒ ๊ตฌํ˜„

---------

Co-authored-by: eunjungL <[email protected]>

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ๊ธฐ๋Šฅ ๋ณ€๊ฒฝ & ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ (#225)

* chore: react-datepick ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ๊ฑฐ

* feat: useCalendar hook ๊ตฌํ˜„

* feat: useClickAway hook ๊ตฌํ˜„

* feat: Calendar ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test: ์บ˜๋ฆฐ๋” ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* feat(TravelPlanRegisterPage): ์บ˜๋ฆฐ๋” ์ปดํฌ๋„ŒํŠธ ํŽ˜์ด์ง€ ๋‚ด ์—ฐ๊ฒฐ

* fix: ์—ฌํ–‰ ๊ณ„ํš ๋ฐ ์—ฌํ–‰๊ธฐ ์•„์ฝ”๋””์–ธ์„ ์—ฐ ์ƒํƒœ์—์„œ ์‚ญ์ œ ์‹œ ๋งˆ์Œ๋Œ€๋กœ ์—ด๋ฆฌ๊ณ  ๋‹ซํžˆ๋Š” ๋ฌธ์ œ ์ˆ˜์ •

value๊ฐ€ ๋ฐฐ์—ด index๋กœ ๋˜์–ด์žˆ์–ด ์‚ญ์ œ ํ•  ๋•Œ ์ธ๋ฑ์Šค ๊ฐ’์ด ์ˆ˜์ •๋˜์–ด ๋ฐœ์ƒํ–ˆ๋˜ ๋ฌธ์ œ์ด๋ฏ€๋กœ place ๋ฐ day๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ uuid๋ฅผ id๋กœ ํ•˜์—ฌ ์ถ”๊ฐ€ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(useTravelPlanDays): onChangePlaceDescription ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€๊ฒฝ

event๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์ด ์•„๋‹Œ description์„ ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

* test(travelPlanRegisterPage): ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ ๊ตฌํ˜„

1. ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก msw ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

2. usePostTravelPlan๋ฅผ wrappingํ•œ createTravelPlanRegisterHook ์ถ”๊ฐ€

3. ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ตฌํ˜„

* refactor: px๋‹จ์œ„ rem์œผ๋กœ ๋ณ€๊ฒฝ

* refactor: StartDate๋ฅผ StartDateLabel๋กœ ๋„ค์ด๋ฐ ์ˆ˜์ •

* [Feature] - ์—ฌํ–‰ ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#226)

* feat: ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ browser ๋ชจํ‚น ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ •

* feat: travelPlan mock ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

* chore: prettier import ์ˆœ์„œ ์ถ”๊ฐ€(contexts, utils)

* refactor: url์—์„œ id ๋ถ„๋ฆฌํ•˜๋Š” ์œ ํ‹ธํ•จ์ˆ˜ ์ถ”๊ฐ€

* refactor: ์—ฌํ–‰๊ธฐ, ์—ฌํ–‰ ๊ณ„ํš endpoint ๋‚ด id type์„ string์œผ๋กœ ๋ณ€๊ฒฝ

* feat: uuid ๊ฒ€์ฆ ํ•จ์ˆ˜ ๋ฐ ์ •๊ทœ ํ‘œํ˜„์‹ ์ถ”๊ฐ€

* feat: ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ/๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•œ ๋ณ€์ˆ˜ ์ถ”๊ฐ€

* refactor(travelogueInfinteHandler): ํ™˜๊ฒฝ์— ๋”ฐ๋ผ request url ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* feat: ์—ฌํ–‰ ๊ณ„ํš mock ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

* refactor(travelPlan.json): ์—ฌํ–‰ ๊ณ„ํš ๋ฐ์ดํ„ฐ ๋‚ด shareKey ์ถ”๊ฐ€

* refactor(travelPlanHandler): 404 httpResponse statusText ๋ณ€๊ฒฝ

* refactor(usePostTravelPlan): mutationFn variable type ์ˆ˜์ •

shareKey๋ฅผ ๋บ€ ํƒ€์ž…์ธ TravelPlanPayload ํƒ€์ž… ์ถ”๊ฐ€

* feat(asset): icon ์ถ”๊ฐ€

* feat(ShareModal): ๊ณต์œ  ๋ชจ๋‹ฌ ๊ตฌํ˜„

* feat: url ๋ณต์‚ฌ๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜ ๊ตฌํ˜„

copyLinkToClipboard ๊ตฌํ˜„

* refactor(ROUTE_PATHS_MAP): travelogue ๋ฐ travelPlan์˜ id variable ํƒ€์ž… ๋ณ€๊ฒฝ

uuid์™€ id ๋ชจ๋‘ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํƒ€์ž… ๋ณ€๊ฒฝ

* refactor(colors): green ์ปฌ๋Ÿฌ theme ๋‚ด ์ถ”๊ฐ€

toast ๊ตฌํ˜„์„ ์œ„ํ•œ green ์ปฌ๋Ÿฌ PRIMITIVE_COLORS ๋‚ด ์ถ”๊ฐ€

* feat: Toast ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test: Toast ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* refactor(Input): forwardRef ์ถ”๊ฐ€

input ๋‚ด ref๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ ๋‚ด forwardRef wrapping

* feat(main): main.tsx ๋‚ด ToastProvider ์ถ”๊ฐ€

* feat: ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„

1. ShareModal ๋‚ด ๋ณต์‚ฌ ์‹œ toast ์ถ”๊ฐ€

2. endpoint ์ถ”๊ฐ€ ๋ฐ ๋ณ€๊ฒฝ

3. TravelPlanPage ๋‚ด shareModal ์—ฐ๊ฒฐ ๋ฐ icon button(๊ณต์œ , ๋”๋ณด๊ธฐ) ์ถ”๊ฐ€

* test(Modal): ๋ณต์‚ฌํ•˜๊ธฐ ๊ธฐ๋Šฅ Modal ์ปดํฌ๋„ŒํŠธ ๋‚ด ์ถ”๊ฐ€

* refactor(Toast): gap ๋‚ด spacing ์ ์šฉ

* refactor(endpoint): ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ๋ฐ ๊ณต์œ ๋œ ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ prefix(/) ์ถ”๊ฐ€

* refactor: extractId ํ•จ์ˆ˜ ๊ฐœ์„ 

* [Feature] - ๏ฟฝ์—ฌํ–‰ ๊ณ„ํš & ์—ฌํ–‰๊ธฐ ์‚ญ์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#229)

* feat(Dropdown): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Dropdown): ์Šคํ† ๋ฆฌ๋ถ ํ…Œ์ŠคํŠธ ๊ตฌํ˜„

* feat(svg-icons): ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

* feat(useDeleteTravelogue): mutation ํ›… ๊ตฌํ˜„

* feat(useDeleteTravelPlan): mutation ํ›… ๊ตฌํ˜„

* feat(TravelogueDeleteModal): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(TravelPlanDeleteModal): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat(TravelogueDetailPage): Text ์ปดํฌ๋„ŒํŠธ๋กœ ์ˆ˜์ • ๋ฐ ๋ถˆํ•„์š”ํ•œ css ์ œ๊ฑฐ, Dropdown ๊ธฐ๋Šฅ ์ถ”๊ฐ€

* feat(TravelPlanDetailPage): Dropdown ๊ธฐ๋Šฅ ์ถ”๊ฐ€

* refactor(Button): ๊ฐœํ–‰ ์ˆ˜์ •

* refactor(Dropdown): ์Šคํ† ๋ฆฌ๋ถ ์ˆ˜์ •

* refactor(Dropdown): ์˜๋ฏธ์˜ ๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด css ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ

* refactor(Dropdown): import type์œผ๋กœ ์ˆ˜์ •

* refactor(index): Dropdown, Modal index์—์„œ ํ˜ธ์ถœํ•˜๋„๋ก ์ˆ˜์ •

* refactor(TravelogueDetailPage): style ์†์„ฑ์„ css๋กœ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ, spacing ์ถ”๊ฐ€ ๋ฐ ์˜๋ฏธ์˜ ๋ช…ํ™•์„ฑ์„ ์œ„ํ•œ isOpen ๋ฐ–์—์„œ ๋ณด์ด๋„๋ก ์ˆ˜์ •

* refactor(TravelPlanDetailPage): style ์†์„ฑ์„ css๋กœ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ, spacing ์ถ”๊ฐ€ ๋ฐ ์˜๋ฏธ์˜ ๋ช…ํ™•์„ฑ์„ ์œ„ํ•œ isOpen ๋ฐ–์—์„œ ๋ณด์ด๋„๋ก ์ˆ˜์ •

* refactor(TravelogueDeleteModal): style ์†์„ฑ์„ css๋กœ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ

* refactor(TravelPlanDeleteModal): style ์†์„ฑ์„ css๋กœ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ

* refactor: title๊ณผ subtitle์ด ๋ฐ”๋€Œ์–ด์žˆ๋Š” ๋ถ€๋ถ„ ์ˆ˜์ •

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Feature] - ๋งˆ์ด ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#236)

* feat: Tab ์ปดํฌ๋„ŒํŠธ์— ์ƒˆ๋กœ๊ณ ์นจํ•ด๋„ ์„ ํƒ๋œ tab ๊ทธ๋Œ€๋กœ์ด๋„๋ก ์ˆ˜์ •

* feat: AvatarCircle์— medium ์‚ฌ์ด์ฆˆ ์ถ”๊ฐ€

* test: AvatarCircle์˜ medium ์‚ฌ์ด์ฆˆ storybook ์ถ”๊ฐ€

* feat: ๋งˆ์ดํŽ˜์ด์ง€ route ์„ค์ •

* feat: Header Drawer์— ๋งˆ์ดํŽ˜์ด์ง€ route ์ฒ˜๋ฆฌ

* feat: ๋งˆ์ดํŽ˜์ด์ง€ tab content์—์„œ ์‚ฌ์šฉ๋  TabContent ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* fix: Tab ์ปดํฌ๋„ŒํŠธ unmount ๋  ๋•Œ ์„ ํƒ๋œ ํƒญ์ด ์ฒซ๋ฒˆ์งธ ํƒญ์ด ๋˜๋„๋ก ์ˆ˜์ •

* style: ํ•„์š”์—†๋Š” ์ฃผ์„ ์‚ญ์ œ

* refactor: Tab ์ปดํฌ๋„ŒํŠธ์— ์ƒˆ๋กœ๊ณ ์นจํ•  ๋•Œ ์ฒ˜์Œ ๋ฒ„ํŠผ์œผ๋กœ ๋Œ์•„๊ฐ”๋‹ค๊ฐ€ ์ตœ๊ทผ๊ป„๋กœ ๋ณด์ด๋Š”๊ฑฐ ์ˆ˜์ •

* feat: useInfiniteMyTravelPlans ๊ตฌํ˜„

* fix: renderItem type ์ˆ˜์ •

* feat: ๋‚ ์งœ ๋ฌธ์ž์—ด์— ์ˆซ์ž๋กœ ์ผ์ˆ˜ ๋”ํ•ด์ฃผ๋Š” util ํ•จ์ˆ˜ ๊ตฌํ˜„

* fix: TravelPlanDetail ํŽ˜์ด์ง€๋ฅผ useGetTravelPlan ๋ฐ˜ํ™˜ ํƒ€์ž…์— ๋งž์ถฐ ์ˆ˜์ •

* feat:  MyTravelPlans ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: MyTravelogues ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* feat: ๋งˆ์ด ํŽ˜์ด์ง€ ๊ตฌํ˜„

* fix: ์“ฐ์ง€ ์•Š๋Š” ๋ณ€์ˆ˜๋“ค ์‚ญ์ œ

* fix: type ์ด๋ฆ„ ์ˆ˜์ •

* fix: ์—ฌํ–‰๊ธฐ ๋“ฑ๋กํŽ˜์ด์ง€์—์„œ type ๋งž์ถฐ์„œ ์ˆ˜์ •

* refactor: Tab ์ปดํฌ๋„ŒํŠธ ์ƒ์ˆ˜ ๋ถ„๋ฆฌ

* refactor: state ์ดˆ๊ธฐ๊ฐ’์„ localStorage์—์„œ ๊ฐ€์ ธ์˜ค๋„๋ก ์ˆ˜์ •

* style: border css ์ˆœ์„œ ์ˆ˜์ •

* style: ์ƒ‰์ƒ ์ฝ”๋“œ ํ•˜๋“œ์ฝ”๋”ฉ ๋Œ€์‹  ๋””์ž์ธ ํ† ํฐ๊ฐ’ ์‚ฌ์šฉ

* refactor: MyPage์—์„œ ํ•„์š”์—†๋Š” useEffect ์ œ๊ฑฐ

* style: font-weight๊ฐ’ ์ˆ˜์ •

* style: ๊ธด css๋ฅผ styled.ts๋กœ ๋ถ„๋ฆฌ

* refactor: TabContent ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์„ MyPageTapContent๋กœ ์ˆ˜์ •

* refactor: MyTravelogue ํƒ€์ž…์„ typesํด๋”๋กœ ์ด๋™

* refactor: MyPageTabContent์˜ props๋ช… ์ˆ˜์ •

* refactor: queries์—์„œ try catch ์ œ๊ฑฐ

* refactor: data ํ‰ํƒ„ํ™”๋ฅผ select๋กœ ๋ฆฌํŒฉํ† ๋ง

* fix: useGetTravelPlan์—์„œ id string๋งŒ ๋ฐ›๋„๋ก ์ˆ˜์ •

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Fix] - 3์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜(๋ฆฌ๋ฒ„)  (#255)

* feat: ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€ ๋‚ด์—์„œ ๋กœ๊ทธ์•„์›ƒ ํ–ˆ์„ ๋•Œ, ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •

* fix: Tab ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์˜ selected index๋กœ ๊ฐ’ ์ดˆ๊ธฐํ™” ์•ˆ๋˜๋˜ ์ด์Šˆ ์ˆ˜์ •

* fix: ์—ฌํ–‰๊ณ„ํš ์ƒ์„ธํŽ˜์ด์ง€, ๋งˆ์ดํŽ˜์ด์ง€์—์„œ ๋กœ๊ทธ์•„์›ƒ ํ•  ์‹œ, ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋„๋ก ์ˆ˜์ •

* style: Drawer์˜ z-index๊ฐ€ transformbottomsheet๋ณด๋‹ค ๋†’๋„๋ก ์ˆ˜์ •

* fix: ์—ฌํ–‰๊ธฐ,์—ฌํ–‰๊ณ„ํš ์‚ญ์ œ์— ๋ฌดํšจํ™” ์ถ”๊ฐ€, ์—ฌํ–‰๊ธฐ ์ž‘์„ฑ์— ๋ฌดํšจํ™” ์ถ”๊ฐ€

* fix: ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ ์—ฌํ–‰๊ธฐ ์ž‘์„ฑ์ž๋“ค ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋ณด์ด๋„๋ก ์ˆ˜์ •

* style: zIndex ๋””์ž์ธ ํ† ํฐ ์ถ”๊ฐ€ ๋ฐ ์ ์šฉ

* feat: Spinner ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

- Icon ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ คํ–ˆ์œผ๋‚˜, Icon ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ์‹œ ๋šœ๋ฆฌ ๋ˆˆ์ด ์‚ฌ๋ผ์ง€๋Š” ์ด์Šˆ๊ฐ€์žˆ์–ด์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค

* test: Spinner storybook ์ถ”๊ฐ€

* feat: LoginFallback ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ ๋ฐ ์ ์šฉ

* test: LoginFallback storybook ์ถ”๊ฐ€

* feat: ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€์— ๋‚ ์งœ ์ •๋ณด ์ถ”๊ฐ€

* fix: Tab ์ปดํฌ๋„ŒํŠธ์— day๊ฐ€ 3๊ฐœ์ผ ๋•Œ ํƒญ๋ฒ„ํŠผ ๊ฐ€๋กœ ๋„“์ด ์ž˜๋ชป ์„ค์ •๋˜๋Š”๊ฑฐ ์ˆ˜์ •

* fix: api ๋ช…์„ธ ์ˆ˜์ •์— ๋”ฐ๋ผ์„œ ์ˆ˜์ •

* style: drawerOverlay ๋”ฐ๋กœ ์ถ”๊ฐ€

* [Fix] - 3์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜(์ง€๋‹ˆ)  (#256)

* fix(TravelPlanDetailPage): ๊ณต์œ  url ์ ‘๊ทผ์— ๋Œ€ํ•œ ๋”๋ณด๊ธฐ ๋ฒ„ํŠผ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* fix(TravelogueDetailPage): ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ ๋ฐœ์ƒ ํ•ด๊ฒฐ

TravelogueTabContent ๋‚ด places์— ์˜ต์…”๋„ ์ฒด์ด๋‹ ์ถ”๊ฐ€

* fix(TravelPlanRegisterPage): ์•„๋ฌด๊ฒƒ๋„ ์ž…๋ ฅํ•˜์ง€ ์•Š๊ณ  ๋“ฑ๋ก์„ ๋ˆŒ๋ €์„ ๋•Œ ์•„๋ฌด ๊ฒƒ๋„ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

startDate๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ๋นˆ ๋ฌธ์ž์—ด๋กœ request ๋‚ ๋ฆฌ๋„๋ก ๋ณ€๊ฒฝ

* fix(TravelPlanRegisterPage): handleAddTravelPlan๋ฅผ mutate๊ฐ€ ์•„๋‹Œ mutateAsync๋กœ ๋ณ€๊ฒฝ

mutateAsync๋กœ ์ธํ•ด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ ๋ฐœ์ƒํ•˜๋Š” ๋ถ€๋ถ„ ํ•ด๊ฒฐ

* fix(MyPage): ๋กœ๊ทธ์ธ ์—†์ด ๋งˆ์ดํŽ˜์ด์ง€๋กœ ์ ‘๊ทผํ•  ๊ฒฝ์šฐ 2๋ฒˆ alert๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(TravelogueDetailPage): ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ ๋‚ด ์ž‘์„ฑ์ž ๋ฐ ์ž‘์„ฑ ์ผ์ž ์ถ”๊ฐ€

* fix(TravelogueRegisterPage): TravelogueDayAccordion ๋‚ด key๋ฅผ id ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ

* feat: ์—ฌํ–‰๊ธฐ ์ƒ์„ธํŽ˜์ด์ง€ ๋‚ด ์Šค์ผˆ๋ ˆํ†ค ์ถ”๊ฐ€

1. GoogleMapLoadScript์—์„œ loadingElement๋ฅผ props๋กœ ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

2. Skeleton ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

3. ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ์Šค์ผˆ๋ ˆํ†ค ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

4. ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€์— ์Šค์ผˆ๋ ˆํ†ค ๋ฐ˜์˜

* refactor(Skeleton): ์Šคํƒ€์ผ ํŒŒ์ผ ๋ถ„๋ฆฌ

* feat: ์—ฌํ–‰ ๊ณ„ํš ํŽ˜์ด์ง€ ๋‚ด ์Šค์ผˆ๋ ˆํ†ค ui ์ถ”๊ฐ€

* feat: ๋งˆ์ดํŽ˜์ด์ง€ ๋‚ด ์Šค์ผˆ๋ ˆํ†ค ui ์ ์šฉ

* fix: ์—ฌํ–‰๊ธฐ & ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋‚ด ๊ตฌ๊ธ€ ๊ฒ€์ƒ‰ ui loading ๊ฐœ์„ 

* fix(TravelPlanDetailPage): ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€ ๋‚ด ์ž‘์„ฑ์ž๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ ๋’ค๋กœ ๊ฐ€๋„๋ก ์ฒ˜๋ฆฌ

* fix(TravelPlanDetailPage): ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ ํ•ด๊ฒฐ

์˜ต์…”๋„ ์ฒด์ด๋‹ ์ถ”๊ฐ€

* fix(interceptor): ๋งŒ๋ฃŒ๋œ ํ† ํฐ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* refactor: ์•„์ฝ”๋””์–ธ์˜ ๊ธฐ๋ณธ ์ƒํƒœ๊ฐ€ ์—ด๋ ค์žˆ๋„๋ก ๋ณ€๊ฒฝ

* fix(interceptor): access token ์—†์„ ์‹œ ์ธ์ฆ ํ—ค๋”์— ๋นˆ ๊ฐ’์„ ๋ณด๋‚ด๋„๋ก ๋ณ€๊ฒฝ

* [Feature] - sentry ์ดˆ๊ธฐ ์„ค์ • ๋ณ€๊ฒฝ & ์†Œ์Šค๋งต ์„ค์ • ์ถ”๊ฐ€ (#261)

* chore(main): dev ํ™˜๊ฒฝ์—์„œ๋งŒ sentry๊ฐ€ ๋™์ž‘ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* chore: @sentry/webpack-plugin ์˜์กด์„ฑ ์ถ”๊ฐ€

* chore: webpack ์„ค์ • ํŒŒ์ผ ๋‚ด sourcemap ๊ด€๋ จ ์„ค์ • ์ถ”๊ฐ€

* [Fix] - 3์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜(์‹œ๋ชจ)  (#262)

* refactor(FloatingButton): ๋ถˆ ํ•„์š”ํ•œ ๋ฒ„ํŠผ๋“ค ์ œ๊ฑฐ

* refactor(Dropdown): dropdown ์™ธ๋ถ€ ํด๋ฆญ์‹œ ๋‹ซ์น˜๋„๋ก ์ˆ˜์ •

* refactor(travelogue): ํƒ€์ž… ์ˆ˜์ •

* refactor(user): ๊ธ€ ์ž‘์„ฑ์ž์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ์œ„ํ•ด์„œ memberId ๋ฅผ ์ „์—ญ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋„๋ก ์ˆ˜์ •

* fix: ์‚ญ์ œ์‹œ ์ฟผ๋ฆฌ ์บ์‹ฑ ์ตœ์‹ ํ™”๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ, error ๊ฐ์ฒด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฌธ์ œ, ๊ทธ๋ฆฌ๊ณ  navigation route ์ˆ˜์ •

* fix: ์‚ญ์ œ์‹œ ์ฟผ๋ฆฌ ์บ์‹ฑ ์ตœ์‹ ํ™”๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(TravelogueDetailPage): ci ๋ฌธ์ œ ํ•ด๊ฒฐ

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Feature] - ๋ฐฐํฌํ•œ ์„œ๋น„์Šค๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋ง ํ•˜๋Š” ๋„๊ตฌ GA ์„ธํŒ…  (#263)

* chore: react-ga4 ์„ค์น˜

* feat(main): ga4 init

* chore: ์ „ํ™˜ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ด๋ฒคํŠธ ์ง‘๊ณ„ํ•˜๋„๋ก ์„ค์ •

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Fix] - ํ•œ Day ๋‚ด ์ค‘๋ณต๋œ ์žฅ์†Œ ์ด๋ฆ„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ๊ฒŒ์‹œ๋ฌผ์ด ์ง€์†์ ์œผ๋กœ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#266)

* fix(TravePlansTabContent): ํ•œ Day ๋‚ด ์ค‘๋ณต๋œ ์žฅ์†Œ ์ด๋ฆ„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ๊ฒŒ์‹œ๋ฌผ์ด ์ง€์†์ ์œผ๋กœ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

์ค‘๋ณต๋œ key๋กœ ์ธํ•ด ๋ฐœ์ƒํ–ˆ๋˜ ๋ฌธ์ œ์ด๋ฏ€๋กœ ๊ณ ์œ ํ•œ ๊ฐ’์ธ id๋กœ ๋ณ€๊ฒฝ

* fix: ์ž˜๋ชป๋œ key prop ํ•ด๊ฒฐ

1. calendar์˜ key๋ฅผ index๊ฐ€ ์•„๋‹Œ date ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ

2. CarouselImageItem์˜ key๋ฅผ imageUrl๋กœ ๋ณ€๊ฒฝ

3. TravelogueTabContent์˜ key๋ฅผ place id๋กœ ๋ณ€๊ฒฝ

* [Fix] - 3์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 2์ฐจ (๋ฆฌ๋ฒ„)  (#276)

* style: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋‚ฉ์ž‘ํ•˜๊ฒŒ ๋ณด์ด๋˜๊ฒƒ ์ˆ˜์ •

* style: Drawer์—์„œ ํด๋ฆญ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์— ๋งˆ์šฐ์Šค ์ปค์„œ pointer์ด๋˜๊ฒƒ ์ˆ˜์ •

* feat: Drawer์— ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ํ™ˆ ๋ฒ„ํŠผ ์ถ”๊ฐ€

* [Fix] - 3์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 2์ฐจ (์‹œ๋ชจ) (#275)

* fix: ์‚ญ์ œ ์ดํ›„ ๋งˆ์ด ํŽ˜์ด์ง€๋กœ ๋Œ์•„์™”์„ ๋•Œ ์บ์‹œ ์ตœ์‹ ํ™” ๋˜์ง€์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(useGetTravelogue): retry 3ํšŒ๋กœ ์ง€์—ฐ๋˜๋Š” ํ˜„์ƒ ํ•ด๊ฒฐ

* fix: ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ƒ์„ธ ์กฐํšŒ์‹œ alert ๋„์šฐ๊ณ  ํŽ˜์ด์ง€ ๋’ค๋กœ ์ด๋™ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(TransformBottomSheet): IconButton์œผ๋กœ ์ˆ˜์ •, ๋ถˆ ํ•„์š”ํ•œ css ์ œ๊ฑฐ ๋ฐ up-arrow layout์— ๋ถ™์€ ๋ฌธ์ œ ํ•ด๊ฒฐ

* [Fix] - 3์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 2์ฐจ (์ง€๋‹ˆ) (#280)

* fix: ํฌ๋กฌ ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ ์บ˜๋ฆฐ๋” ๋ฐ‘์ค„ ๋ณด์ด๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

meta tag ์ถ”๊ฐ€

* fix(TravelPlansTabContent): ์—ฌํ–‰ ์ƒ์„ธ ํŽ˜์ด์ง€ ๋‚ด ๋งˆ์ง€๋ง‰ ์š”์†Œ๊ฐ€ ๋ฐ”ํ…€ ์‹œํŠธ๋กœ ์ธํ•ด ๋ณด์—ฌ์ง€์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(TravelPlansTabContent): ์—ฌํ–‰ ๊ณ„ํš ๋‚ด description ์ถ”๊ฐ€

* fix(TravelogueMultiImageUpload): ์žฅ์†Œ ๋ณ„ ์‚ฌ์ง„ 10์žฅ ์ดํ•˜๋กœ ์—…๋กœ๋“œ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(GoogleMapView): ๋งˆ์ปค ๋‚ด ์ˆœ์„œ ํ‘œ์‹œ ํ…์ŠคํŠธ ์ถ”๊ฐ€

* fix(Calendar): key prop ๋ณ€๊ฒฝ

* refactor(TravelPlanRegisterPage): ์ฃผ์„ ์ฒ˜๋ฆฌ ๋œ ๋ถ€๋ถ„ ์ˆ˜์ •

* refactor: ๋งˆ์ปค ์ƒ‰์ƒ ๋ณ€๊ฒฝ & ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ title & subtitle ์ˆœ์„œ ๋ณ€๊ฒฝ (#283)

* refactor: ๋งˆ์ปค ์ƒ‰์ƒ ๋ณ€๊ฒฝ

* refactor(TravelogueDetailPage): ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ title, subtitle ์ˆ˜์ •

* [Fix] - ๋งŒ๋ฃŒ๋œ access token ํ•ธ๋“ค๋ง (#292)

* fix(interceptor): ๋งŒ๋ฃŒ ํ† ํฐ ์—๋Ÿฌ ์‹œ early return ํ•˜์—ฌ error๋ฅผ throw ํ•˜์ง€ ์•Š๋„๋ก ๋ณ€๊ฒฝ

* fix: onSuccess callback ๋‚ด์—์„œ ๊ตฌ์กฐ ๋ถ„ํ•ด ํ• ๋‹น์„ ํ•˜์ง€ ์•Š๋„๋ก ๋ณ€๊ฒฝ

* refactor: ์ˆ˜์ • ui ์ œ๊ฑฐ

* [Fix] - ์‚ญ์ œ ๋ฐ ๋“ฑ๋ก ์‹œ ์—ฌ๋Ÿฌ๋ฒˆ ์š”์ฒญํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ์ˆ˜์ • (#295)

* feat(useLeadingDebounce): ์„ ํ–‰ ๋””๋ฐ”์šด๋“œ ํ›… ๊ตฌํ˜„

* fix: ์‚ญ์ œ ๋ฐ˜๋ณต ์š”์ฒญํ•˜์ง€ ์•Š๋„๋ก ์ˆ˜์ •

* fix: ๋“ฑ๋ก ๋ฐ˜๋ณต ์š”์ฒญํ•˜์ง€ ์•Š๋„๋ก ์ˆ˜์ •

* refactor(useLeadingDebounce): ๋ Œ๋”๋ง๊ณผ ๋ฌด๊ด€ํ•˜๊ธฐ์— useState ์—์„œ useRef๋กœ ์ˆ˜์ •

* [Feature] - refresh token ํด๋ผ์ด์–ธํŠธ ๋‚ด ์ ์šฉ (#307)

* feat: ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ์ถ”๊ฐ€

1. ๋กœ๊ทธ์•„์›ƒ ์‹œ refresh token empty string์œผ๋กœ ๋ณ€๊ฒฝ

2. ๋กœ๊ทธ์ธ ์‹œ refresh token localstorage ๋‚ด ์ถ”๊ฐ€

3. AuthTokenResponse ๋‚ด refreshToken ์ถ”๊ฐ€

* feat: ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ํด๋ผ์ด์–ธํŠธ ๋‚ด ์ ์šฉ

1. handleAPIError ๋‚ด 401 ์—๋Ÿฌ ์‹œ access token ์žฌ๋ฐœ๊ธ‰ ๋กœ์ง ์ถ”๊ฐ€

2. ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ logout ๋กœ์ง ์ถ”๊ฐ€

* [Feature] - TravelogueCard ์ปดํฌ๋„ŒํŠธ ๋ฆฌํŒฉํ„ฐ๋ง (#314)

* refactor(svg-icons): empty-heart ์•„์ด์ฝ˜ ๋ณ€๊ฒฝ

* refactor: travelogue mock data ์ˆ˜์ •

* refactor(travelogue): TravelogueRepsonse ํƒ€์ž… ๋ณ€๊ฒฝ

ํ˜„์žฌ ๋ช…์„ธ์— ๋งž๊ฒŒ ๋ณ€๊ฒฝ

* test(TravelogueCard): likes ํ•„๋“œ๋ฅผ likeCount๋กœ ๋ณ€๊ฒฝ

* refactor: TravelogueCard ui ํ˜•ํƒœ ๋ฆฌํŒฉํ„ฐ๋ง

* refactor: ์—ฌํ–‰๊ธฐ mock data ์ถ”๊ฐ€

* refactor: TravelogueOverview ํƒ€์ž… ์ œ๊ฑฐ

TravelogueResponse ํƒ€์ž…์„ Pick ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝ

* [Feature] - Input ์ปดํฌ๋„ŒํŠธ ๋ฆฌํŒฉํ† ๋ง (#310)

* feat: Input ์ปดํฌ๋„ŒํŠธ์— variants ์ถ”๊ฐ€

- border bottom์ด ์žˆ๋Š” input ์ถ”๊ฐ€
- focus ํ–ˆ์„ ๋•Œ๋งŒ border bottom์ด ์ƒ๊ธฐ๋Š” input ์ถ”๊ฐ€

* test: ์ถ”๊ฐ€๋œ Input storybook ์ถ”๊ฐ€

* fix: ์•ˆ์“ฐ๋Š” import๋ฌธ ์‚ญ์ œ

* refactor: InputVariants type ์ˆ˜์ •

* Fix - image error ์ฒ˜๋ฆฌ ๋ˆ„๋ฝ, ์—ฌํ–‰๊ธฐ ์‚ญ์ œ์‹œ ๋งˆ์ดํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐˆ ๋•Œ tab ์ดˆ๊ธฐ๊ฐ’ ์ˆ˜์ • , ์—ฌํ–‰๊ธฐ ์ธ๋„ค์ผ (#296)

* fix: PlaceDetailCard์—์„œ ์ด๋ฏธ์ง€ ์—๋Ÿฌ ํ•ธ๋“ค๋ง ์ถ”๊ฐ€

* test: PlaceDetailCard storybook ์ถ”๊ฐ€

* fix: ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ์กฐํšŒ ์ธ๋„ค์ผ ๊ฐ€์šด๋ฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์œ„์ชฝ ๋ณด์ด๋Š” ์ด์Šˆ ์ˆ˜์ •

* fix: ๋‚ด ์—ฌํ–‰๊ธฐ ์‚ญ์ œ ํ›„ ๋งˆ์ดํŽ˜์ด์ง€ ์ด๋™์‹œ, tab์ด ๋‚ด ์—ฌํ–‰๊ธฐ๋กœ ๊ฐ€์žˆ๋„๋ก ์ˆ˜์ •

* [Fix] - Icon, Icon Button storybook์—์„œ iconType option ์ ์šฉ๋˜๋„๋ก ์ˆ˜์ • (#327)

* test: Icon storybook iconType option ์ ์šฉ๋˜๋„๋ก ์ˆ˜์ •

* test: IconButton storybook iconType option ์ ์šฉ๋˜๋„๋ก ์ˆ˜์ •

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš TO DO ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#333)

* feat: asset ์ถ”๊ฐ€(check)

* feat: Checkbox ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Checkbox): ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* refactor(Input): label๊ณผ count๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋„๋ก ๋ณ€๊ฒฝ

* test: Input ์ปดํฌ๋„ŒํŠธ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•œ Calendar & Modal ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์—…๋ฐ์ดํŠธ

* feat: PlaceTodoListItem ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test: PlaceTodoListItem ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* refactor(Input): Input ์Šคํƒ€์ผ๋ง ๋ณ€๊ฒฝ

* refactor(travelPlan): TravelPlanPlace ํƒ€์ž… ๋ช…์„ธ ๋ณ€๊ฒฝ

1. todos ํ•„๋“œ ์ถ”๊ฐ€

2. TravelPlanTodo ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€

* refactor(travelPlan): TravelPlanTodo id ๋ช…์„ธ ๋ณ€๊ฒฝ

* refactor(TravelPlanRegisterPage): description์ด ์•„๋‹Œ todo๋ฅผ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(travelPlan): TravelPlanPlace ๋‚ด description ํ•„๋“œ ์ œ๊ฑฐ

* refactor: ์—ฌํ–‰ ๊ณ„ํš mock ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ๋œ ๋ช…์„ธ์— ๋งž๊ฒŒ ์ˆ˜์ •

* refactor(Checkbox): checked๊ฐ€ ์•„๋‹Œ defaultChecked๋กœ ๋ณ€๊ฒฝ

๋ธŒ๋ผ์šฐ์ € warning์œผ๋กœ ์ธํ•œ defaultChecked๋กœ ๋ณ€๊ฒฝ

* refactor(endpoint): todo patch ์š”์ฒญ ๊ด€๋ จ endpoint ์ถ”๊ฐ€

* test: ๊ณต์œ  ๋งํฌ๋กœ ์ ‘์†ํ•œ ์—ฌํ–‰ ๊ณ„ํš msw handler ์ถ”๊ฐ€

* test: ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ msw ํ•ธ๋“ค๋Ÿฌ ๋ณ€๊ฒฝ

uuid ํ™•์ธํ•˜๋Š” ๋กœ์ง ์ œ๊ฑฐ

* test: ์—ฌํ–‰ ๊ณ„ํš todo patch ์š”์ฒญ msw ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

* feat(usePatchTravelPlanTodo): ์—ฌํ–‰ ๊ณ„ํš todo patch ์š”์ฒญ ๊ด€๋ จ query ๊ตฌํ˜„

* feat: TravelPlanTodoItem ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor(TravelPlansTabContent): description text๊ฐ€ ์•„๋‹Œ todo list๋“ค์ด ๋ณด์—ฌ์ง€๋„๋ก ๋ณ€๊ฒฝ

* refactor(useTravelPlanDays): onAddPlaceTodo ๋‚ด ๋…ผ๋ฆฌ or ์—ฐ์‚ฐ์ž๊ฐ€ ์•„๋‹Œ ๋„ ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž๋กœ ๋ณ€๊ฒฝ

* test(travelPlanRegisterPage): ์—ฌํ–‰ ๋“ฑ๋ก ํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ ๋‚ด ์žฅ์†Œ ์„ค๋ช… ๋ณ€๊ฒฝ test ์ œ๊ฑฐ

* fix(TravelPlanTodoItem): ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ action์„ ์ผ์œผํ‚จ ์ƒํƒœ๋กœ request ๋‚ ๋ฆฌ๋„๋ก ๋ณ€๊ฒฝ

* fix: ci ๋ฌธ์ œ ํ•ด๊ฒฐ

checkbox index.ts ๋‚ด default export ์ถ”๊ฐ€

* refactor(TravelPlanTodoItem): gap์— spacing ์ ์šฉ

* refactor(PlaceTodoItem): Wrapper๊ฐ€ ์•„๋‹Œ Container๋กœ ๋ณ€๊ฒฝ

์—ฌ๋Ÿฌ ์š”์†Œ๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ปจ๋ฒค์…˜์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ

* refactor: ๋ถˆํ•„์š”ํ•œ console.log ์ œ๊ฑฐ

* refactor(Checkbox): checked, defaultChecked๋ฅผ ์™ธ๋ถ€์—์„œ ์ฃผ์ž… ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

์ œ์–ด ์ปดํฌ๋„ŒํŠธ, ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋˜์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ

* [Feature] - tag ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#335)

* refactor(TravelogueCard): layout css ์ˆ˜์ •

* refactor(Text): bodyBold, detailBold ์ถ”๊ฐ€

* feat(Chip): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(Chip): ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* refactor(Chip): isSelected ์ดˆ๊ธฐ๊ฐ’ ์„ค์ • ๋ฐ optional๋กœ ์ˆ˜์ •

* feat(travelogue): tag type ์ถ”๊ฐ€

* feat(TravelogueDetailPage): ํ…Œ๊ทธ UI ๊ตฌํ˜„

* feat(TravelogueCart): tag UI ์ถ”๊ฐ€

* refactor(Chip): button ์—์„œ li๋กœ ๋ณ€๊ฒฝ

* refactor(useDragScroll): ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ์œ„ํ•˜์—ฌ li๋กœ ๋ณ€๊ฒฝ ํ›„ ์ ์šฉ

* feat(index): Chip ์ถ”๊ฐ€

* refactor: chips ul๋กœ ๋ณ€๊ฒฝ

* feat(tags): tags endpoint ๋ฐ queryKey ์ถ”๊ฐ€

* feat(useGetTags): tags type ์ถ”๊ฐ€ ๋ฐ getTags ๊ตฌํ˜„

* feat(TravelogueRegisterPage): ํƒœ๊ทธ UI ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(TravelogueRegisterPage): ํƒœ๊ทธ UI ๋„˜์–ด๊ฐ€๋Š” ํ™”๋ฉด ๋๊นŒ์ง€ ๋‹ฟ๋„๋ก ์ˆ˜์ • ๋ฐ ํƒœ๊ทธ ์„ ํƒ 3๊ฐœ๊นŒ์ง€๋งŒ ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(Tab): no-wrap์€ ์—†๋Š” ์†์„ฑ์ด๋ผ nowrap์œผ๋กœ ์ˆ˜์ •

* feat(useInfiniteTravelogues): ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ ์ถ”๊ฐ€

* feat(travelogue): ํƒœ๊ทธ ์ถ”๊ฐ€์— ๋”ฐ๋ฅธ mock data ๋ฐ handler ์ˆ˜์ •

* feat(MainPage): ํƒœ๊ทธ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor(createInfiniteTravelogueHook): ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜์ •

* refactor(chip): ์Šคํ† ๋ฆฌ๋ถ options ์ถ”๊ฐ€

* refactor(Chip): line-height ์ถ”๊ฐ€

* refactor(MultiImageUpload): div๋กœ ์ˆ˜์ •

* refactor: chips๋ฅผ chipsContainer๋กœ ์ˆ˜์ •

* feat(queryKey): travelogue.tag ์ถ”๊ฐ€

* refactor(useDragScroll): ํƒ€์ž… ์œ ์—ฐ์„ฑ์„ ์œ„ํ•ด ์ œ๋„ค๋ฆญ์œผ๋กœ ์ˆ˜์ •

* feat(condition): condition ์ƒ์ˆ˜ํ™”

* refactor(useInfiniteTravelogues): ์ƒ์ˆ˜ ์™ธ๋ถ€๋กœ ์ด๋™ ๋ฐ queryKey ์ƒ์ˆ˜ํ™” ํ™œ์šฉ

* refactor: useDragScroll ์ œ๋„ค๋ฆญ ์ˆ˜์ •์— ๋”ฐ๋ฅธ ๋ณ€๊ฒฝ

* refactor(TravelPlanRegisterPage): ์ƒ์ˆ˜ํ™”์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* refactor(MainPage): ์ƒ์ˆ˜ํ™” ํ™œ์šฉ, useDragScroll ์ œ๋„ค๋ฆญ ์ ์šฉ ๋ฐ chipsContainer๋กœ ๋ณ€๊ฒฝ

* feat(useTagSelection): ํ›… ๊ตฌํ˜„ ๋ฐ ์ ์šฉ

* refactor(formValidation): condition ๋„ค์ด๋ฐ ์ˆ˜์ •

* [Feature] - ์—ฌํ–‰๊ธฐ ์žฅ์†Œ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ค‘์ผ ๊ฒฝ์šฐ, spinner๋ฅผ ๋ณด์—ฌ์ฃผ๋„๋ก ๋ฆฌํŒฉํ„ฐ๋ง (#332)

* refactor(Spinner): Spinner ์ปดํฌ๋„ŒํŠธ ๋‚ด variants ๋ฐ size option ์ถ”๊ฐ€

circle spinner ๋ฐ ํ™•์žฅ์„ฑ์„ ์œ„ํ•ด ํ•ด๋‹น option๋“ค ์ถ”๊ฐ€

* test: Spinner ์ปดํฌ๋„ŒํŠธ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€

* refactor(MultiImageUpload): ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ ๋‚ด image upload ์ค‘์ผ ์‹œ loading ui๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋„๋ก ์ปดํฌ๋„ŒํŠธ ๋ฆฌํŒฉํ„ฐ๋ง

* test(MultiImageUpload): ์ปดํฌ๋„ŒํŠธ ๋ณ€๊ฒฝ์ ์— ๋”ฐ๋ฅธ ์Šคํ† ๋ฆฌ๋ถ ๋ณ€๊ฒฝ

* refactor: ๋ถˆํ•„์š”ํ•œ console.log ์ œ๊ฑฐ

* fix(MultiImageUpload): x ๋ฒ„ํŠผ์ด ์งค๋ ค์„œ ๋ณด์ด๋Š” ๋ฌธ์ œ ์ˆ˜์ •

* fix(TravelogueMultiImageUpload): ๊ฐ™์€ image๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์—…๋กœ๋“œ ์‹œ ์—…๋กœ๋“œ๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

fileInputRef๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(TravelogueMultiImageUpload): ์ตœ๋Œ€ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ฐฏ์ˆ˜ ์ƒ์ˆ˜ํ™” ๋ฐ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(TravelogueMultiImageUpload): newImgUrls๋ฅผ newImageUrls๋กœ ๋ณ€๊ฒฝ

๋‹ค๋ฅธ ๋ณ€์ˆ˜๋“ค์—์„œ image๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋งŒํผ img๊ฐ€ ์•„๋‹Œ image๋กœ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ

* refactor(TravelogueMultiImageUpload): props interface ๋ถ„๋ฆฌ

* refactor(TravelogueMultiImageUpload): ๋‚ด๋ถ€ ๋กœ์ง hook์œผ๋กœ ๋ถ„๋ฆฌ

* refactor: imageStates์— lazy ์ดˆ๊ธฐํ™” ์ ์šฉ

* [Feature] - ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ ์ˆ˜์ • (#317)

* feat: ๋‹‰๋„ค์ž„ ์ˆ˜์ • msw ์ถ”๊ฐ€

* feat: ๋‹‰๋„ค์ž„์ˆ˜์ • hook ๊ตฌํ˜„

* fix : ๋‹‰๋„ค์ž„ ์ˆ˜์ • api ๋ช…์„ธ์— ๋งž์ถฐ์„œ msw,query,endpoint ์ˆ˜์ •

* fix: ๋‹‰๋„ค์ž„ ์ˆ˜์ • hook์—์„œ refetchType ์ˆ˜์ •

* feat : ๋งˆ์ด ํŽ˜์ด์ง€์— ํ”„๋กœํ•„ ์ˆ˜์ • ๊ธฐ๋Šฅ ์ถ”๊ฐ€

* style: ๊ธ€์”จ ์ƒ‰์ƒ theme color๋กœ ์ˆ˜์ •

* fix: ํ•จ์ˆ˜๋ช…์„ ํŒŒ์ผ๋ช…๊ณผ ๋™์ผํ•˜๊ฒŒ ์ˆ˜์ •

* fix: refetchType ์‚ญ์ œ

- ์—†์• ๋„ ์ž˜๋˜๊ธฐ์— ์‚ญ์ œํ•จ

* fix: console.log๋ฅผ alert๋กœ ์ˆ˜์ •

* fix : ref ์‚ฌ์šฉ, ๋‹‰๋„ค์ž„์„ ๋‹ค ์ง€์šฐ๊ณ  ์ˆ˜์ • ์‹œ๋„ํ•  ๊ฒฝ์šฐ ์›๋ž˜ ๋‹‰๋„ค์ž„์œผ๋กœ ๋˜๋„๋ก๊ฐ€๋„๋ก ์ˆ˜์ •

Co-authored-by: jinyoung <[email protected]>

* chore: ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” styled ์‚ญ์ œ

* fix : ๋นˆ ์นธ์œผ๋กœ ์ˆ˜์ • ์‹œ๋„ํ•  ๊ฒฝ์šฐ ์›๋ž˜ ๋‹‰๋„ค์ž„์œผ๋กœ ๋˜๋Œ์•„๊ฐ€๋„๋ก ์ˆ˜์ •

* fix: ๋‹‰๋„ค์ž„ ์ˆ˜์ •์‹œ ๊นœ๋นก์ด๋ฉฐ ๋ Œ๋”๋ง ๋˜๋Š”๊ฒƒ ์ˆ˜์ •, spellcheck false๋กœ ์„ค์ •

---------

Co-authored-by: jinyoung <[email protected]>

* [Feature] - ๊ฒ€์ƒ‰ ๊ตฌํ˜„ (#328)

* feat: ์—ฌํ–‰๊ธฐ ๊ฒ€์ƒ‰ ๋ฌดํ•œ์Šคํฌ๋กค query ๊ตฌํ˜„

* chore: ๊ฒ€์ƒ‰ ์•„์ด์ฝ˜ ์ถ”๊ฐ€

* feat: ํ—ค๋”์— ๊ฒ€์ƒ‰ ์ถ”๊ฐ€

* feat: SearchFallback ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€

* feat: ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํŽ˜์ด์ง€ ๊ตฌํ˜„

* feat: ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ ๋ผ์šฐํŠธ ์ถ”๊ฐ€

* feat: home icon ์ถ”๊ฐ€

* refactor: Header ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ธฐ๋ณธ Header์˜ basic์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฆฌํŒฉํ† ๋ง

* feat: HomeHeader ๊ตฌํ˜„

* feat: LogoHeader ๊ตฌํ˜„

* feat: NavigationHeader ๊ตฌํ˜„

* feat: SearchHeader ๊ตฌํ˜„

* fix: storybook preview rootStyle์ด common/Header์—๋Š” ๋‹ค๋ฅด๊ฒŒ ์ ์šฉ๋˜๋„๋ก ์ˆ˜์ •

- rootStyle์— ๋“ค์–ด๊ฐ€์žˆ๋Š” padding ๋•Œ๋ฌธ์— Header storybook์—์„œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ padding๋งŒํผ ๋ฐ€๋ฆฌ๋Š” ์ด์Šˆ๊ฐ€์žˆ์–ด์„œ common/Header์ผ๋•Œ๋Š” padding์ด 0์ด ๋˜๋„๋ก ์ˆ˜์ •ํ•จ

* test: Header storybook ์ถ”๊ฐ€

* feat: AppLayout์—์„œ Header๋ฅผ ๋™์ ์œผ๋กœ ์ถ”๊ฐ€

* refactor: HomeHeader -> HomePageHeader๋กœ ์ด๋ฆ„ ์ˆ˜์ •

* refactor: ์Šคํƒ€์ผ๋“œ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ์ˆ˜์ • (wrapper -> container)

* refactor: Header Props๋ช… ์ˆ˜์ •

* refactor: ๊ฒ€์ƒ‰์–ด ์ตœ์†Œ ๊ธ€์ž์ˆ˜ ์ƒ์ˆ˜ํ™”

* refactor: AppLayout์—์„œ pathname ํ™•์ธ ๋ถ€๋ถ„ ์ƒ์ˆ˜ ์‚ฌ์šฉ

* refactor: h1 ํƒœ๊ทธ ๋Œ€์‹  Text ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฆฌํŒฉํ† ๋ง

* refactor: gap ๊ฐ’์— theme spacing์„ ์‚ฌ์šฉ

* refactor: gap ๊ฐ’์— theme spacing ์‚ฌ์šฉ

* chore: ์ฝ”๋“œ ์‚ฌ์ด์— ๊ฐœํ–‰ ์ถ”๊ฐ€

* chore: ๊ฐœํ–‰์ถ”๊ฐ€

* refactor: Icon ๋Œ€์‹  IconButton์„ ์‚ฌ์šฉ

* refactor: #fff ๋Œ€์‹  primitive white ์‚ฌ์šฉ

* chore: ๋นˆ ํŒŒ์ผ ์‚ญ์ œ

* refactor: dom์œผ๋กœ ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ๋ถ€๋ถ„ ref๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

* fix: ๊ฒ€์ƒ‰์–ด์— trim ์ถ”๊ฐ€ ๋ฐ  useInfiniteSearchTravelogues ๊ฐ€ keyword๊ฐ€ ๋นˆ๊ฐ’์ด ์•„๋‹๋•Œ๋งŒ ์š”์ฒญ๋˜๋„๋ก ์ˆ˜์ •

* refactor: NavigationHeader -> SearchResultPageHeader๋กœ ์ด๋ฆ„ ์ˆ˜์ •

* fix: Header ์ด๋ฆ„ ์ˆ˜์ • ๊ผฌ์ธ๊ฒƒ ์ˆ˜์ •

* refactor: Header ๊ด€๋ จ ์ปดํฌ๋„ŒํŠธ ์ธ๋ฑ์‹ฑ

* fix: ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ˆ„๋ฅผ ๋•Œ, query๋Š” ๊ทธ์ „ ๊ฒ€์ƒ‰์–ด์ง€๋งŒ Input value๋Š” ๊ทธ์ „ ๊ฒ€์ƒ‰์–ด๊ฐ€ ์•„๋‹ˆ๋˜ ์ด์Šˆ ์ˆ˜์ •

* storybook: styled์˜ Input์ด ์•„๋‹Œ ์ง„์งœ Input.tsx ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

- ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฌธ์ œ์—†์ด ์ž˜ ๋ Œ๋”๋ง๋˜๋‚˜, storybook์—์„œ๋Š” ๊ฐ’์„ ๋„ฃ์ง€ ์•Š์€ label,maxcount,count div๊นŒ์ง€ ๋งŒ๋“œ๋Š” ์ด์Šˆ๊ฐ€์žˆ์Šต๋‹ˆ๋‹ค.
- ์ผ๋‹จ style๋กœ marginbottom์— ์Œ์ˆ˜๋ฅผ ์ค˜์„œ ๊ฐ€์šด๋ฐ์ •๋ ฌ๋œ๊ฑฐ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ์ˆ˜์ •์€ํ•ด๋†จ์Šต๋‹ˆ๋‹ค

* fix: build ์—๋Ÿฌ ์žก์Œ

* [Feature] - ์—ฌํ–‰๊ธฐ ์ƒ์„ธ๋ณด๊ธฐ ํŽ˜์ด์ง€์—์„œ ์ง€๋„ ์ƒ์„ธ๋ณด๊ธฐ ๊ตฌํ˜„ (#334)

* feat: ์ง€๋„ ์•„์ด์ฝ˜ ์ถ”๊ฐ€

* style: Box ๋†’์ด ์ˆ˜์ •

* feat: ์ง€๋„ ์•„์ด์ฝ˜ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๊ตฌ๊ธ€๋งต ์‚ฌ์ดํŠธ๋กœ ์ด๋™ํ•˜๋„๋ก ๊ตฌํ˜„

- place ๋ฐ์ดํ„ฐ ์•ˆ์— ๊ตฌ๊ธ€๋งต placeId๊ฐ€ ์—†์–ด ์ผ๋‹จ lat,lng,placeName์œผ๋กœ ๊ตฌํ˜„(์ •ํ™•ํ•œ ๊ฒฐ๊ณผ ๋‚˜์˜ค์ง€ ์•Š๋Š”๊ฒƒ๋„ ์žˆ์Œ)

* fix: Box ์ปดํฌ๋„ŒํŠธ์—์„œ tag ์‚ญ์ œ

- Box์—์„œ tag ์•ˆ์“ฐ๊ธฐ๋กœํ•ด์„œ ์‚ญ์ œํ•จ

* chore: ํ•„์š”์—†๋Š” ํƒœ๊ทธ ์‚ญ์ œ

* fix: build ์—๋Ÿฌ ์žก๊ธฐ

* [Feature] - ์—ฌํ–‰๊ธฐ ์ข‹์•„์š” ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#342)

* feat: asset(heart) ์ถ”๊ฐ€

* refactor(TravelogueDetailPage): ์ข‹์•„์š” ๋””์ž์ธ ์ˆ˜์ •

1. flex-end๊ฐ€ ์•„๋‹Œ space-between์œผ๋กœ ๋ณ€๊ฒฝ

2. gap 8px๋กœ ๋ณ€๊ฒฝ

* feat: ์ข‹์•„์š” ๊ด€๋ จ msw ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

* feat: ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ์กฐํšŒ msw ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

* refactor: ์—ฌํ–‰๊ธฐ mock ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ

isLiked ๋ฐ likeCount ์ถ”๊ฐ€

* refactor: ๋ฉ”์ธ ํŽ˜์ด์ง€ ์—ฌํ–‰๊ธฐ ํ•ธ๋“ค๋Ÿฌ ๋ณ€๊ฒฝ

request ๊ฐ์ฒด ์—†์„ ๊ฒฝ์šฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* refactor(travelogue): TraveloguePayload ๋ฐ TravelogueResponse ํƒ€์ž… ๋ณ€๊ฒฝ

1. TraveloguePayload์„ Omit์ด ์•„๋‹Œ Pick์œผ๋กœ ๋ณ€๊ฒฝ

2. TravelogueResponse ํƒ€์ž… ๋‚ด likeCount ๋ฐ isLiked ์ถ”๊ฐ€

* feat(endpoint): ์—ฌํ–‰๊ธฐ ์ข‹์•„์š” endpoint ์ถ”๊ฐ€

* feat: ์—ฌํ–‰๊ธฐ active ๋ฐ inactive ๊ด€๋ จ query ์ถ”๊ฐ€

* feat(TravelogueDetailPage): ์—ฌํ–‰๊ธฐ ์ข‹์•„์š” ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor(TravelogueDetailPage): ์—ฌํ–‰๊ธฐ๋ฅผ ๋“ฑ๋กํ•œ ์‚ฌ๋žŒ๋งŒ ์ข‹์•„์š”๋ฅผ ํ† ๊ธ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •

* refactor(svg-icons): heart, empty-heart์— ๋Œ€ํ•œ path ๋ณ€๊ฒฝ

* refactor(asset): ์ข‹์•„์š” svg ๋ณ€๊ฒฝ

* refactor(Icon): icon viewBox๋ฅผ size๋กœ ๋ฐ›๋„๋ก ๋ณ€๊ฒฝ

* refactor: ์ข‹์•„์š” icon button ์‚ฌ์ด์ฆˆ 16์œผ๋กœ ๋ณ€๊ฒฝ

* refactor: ์ข‹์•„์š” ์ฟผ๋ฆฌ ๊ด€๋ จ refetch type all๋กœ ๋ณ€๊ฒฝ

* refactor(useGetTravelogue): access token์ด ์Šคํ† ๋ฆฌ์ง€์— ์žˆ์„ ๊ฒฝ์šฐ ์˜ˆ์™ธ์ ์œผ๋กœ ์ธ์ฆ ํ—ค๋” ์ถ”๊ฐ€ ํ•˜๋„๋ก ๋ณ€๊ฒฝ

๋ฐฑ์—”๋“œ ์ธก์—์„œ ์ธ์ฆ ํ—ค๋” ์—†์ด๋Š” ์œ ์ € ์ข‹์•„์š” ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์–ด๋ ต๋‹ค๊ณ  ํ•˜์…”์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ

* refactor(TravelogueDetailPage): ๋กœ๊ทธ์ธ ํ•œ ๊ฒฝ์šฐ ๋ฌด์กฐ๊ฑด ์ข‹์•„์š”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€๊ฒฝ

* refactor(Icon): viewbox๋ฅผ ๋‹ค์‹œ svg-icons์˜ width, height๋กœ ์„ค์ •ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor: query ๋‚ด refetchType ์—†์• ๋Š” ๊ฑธ๋กœ ๋ณ€๊ฒฝ

์ƒ์„ธ ํŽ˜์ด์ง€๋งŒ refetch ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* [Feature] - ์ธ๋„ค์ผ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€ (#356)

* refactor(TravelogueRegisterPage): ์ธ๋„ค์ผ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* refactor: api endpoint ์›๋ž˜๋Œ€๋กœ ๋ณ€๊ฒฝ

* [๏ฟฝFeature] - ์—ฌํ–‰๊ธฐ ๋ฐ ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜์ • ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#348)

* refactor(ModalBottomSheet): ์ˆ˜์ •ํŽ˜์ด์ง€์—์„œ๋„ ์‚ฌ์šฉํ•˜๋„๋ก props ์œ ์—ฐํ•˜๊ฒŒ ์ˆ˜์ •

* feat(route): ์ˆ˜์ • ํŽ˜์ด์ง€ route ์ถ”๊ฐ€

* refactor(RegisterPage): modalBottomSheet props ์ˆ˜์ •์— ๋”ฐ๋ฅธ ๋ฆฌํŒฉํ† ๋ง

* feat(DetailPage): ์ˆ˜์ • ๋ฒ„ํŠผ ํ™œ์„ฑํ™”

* feat(TravelogueEditPage): UI ๊ตฌํ˜„

* feat(TravelPlanEditPage): UI ๊ตฌํ˜„

* refactor(errorMessage): only writer ์†์„ฑ๋ช…์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ˆ˜์ •

* refactor: state๋ฅผ set ์‹œํ‚ค๋Š” change ํ•จ์ˆ˜ ๊ตฌํ˜„ ๋ฐ ๋ฐ˜ํ™˜ํžˆ๋„๋ก ์ˆ˜์ •

* feat(TravelogueEditPage): ์ดˆ๊ธฐ๊ฐ’ ์„ค์ •, ํƒœ๊ทธ ui ์ถ”๊ฐ€ ๋ฐ ํƒ€ ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜์ •ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor(router): ์˜คํƒ€ ์ˆ˜์ •

* refactor(BackDrop): position fixed๋กœ ์ˆ˜์ •

* refactor(useTravelogueDays):  change ํ•จ์ˆ˜๋ช… ์ˆ˜์ •

* refactor(TravelPlanRegisterPage): mutate ๋„ค์ด๋ฐ ์ˆ˜์ •

* feat(errorMessage): errorMessage ์ถ”๊ฐ€

* refactor(PlaceTodoListItem): value ๊ฐ’ ๋ฐ isChecked ๊ฐ’ ๋ฐ›๋„๋ก ์ˆ˜์ •

* feat(usePutTravelogue): ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(usePutTravelPlan): ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(useTravelPlanDays): onChange ํ•จ์ˆ˜ ์ถ”๊ฐ€

* feat(TravelPlanEditPage): ๊ฐ’ ์ดˆ๊ธฐํ™”, put ์š”์ฒญ ๋ฐ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor: useEffect ์˜์กด์„ฑ ๋ฐฐ์—ด๋กœ ์‚ฌ์šฉํ•˜์—ฌ useCallback์œผ๋กœ ์ˆ˜์ •

* feat(debouncedTime): ์ƒ์ˆ˜ํ™”

* refactor(extractId): ์žฌ์‚ฌ์šฉ์„ฑ์„ ์œ„ํ•œ ์ˆ˜์ •

* feat(extractUTCDate):UTC Date ์ถ”์ถœ ํ•จ์ˆ˜ ์œ ํ‹ธํ™”

* refactor(travelPlan): days ํƒ€์ž… ์ˆ˜์ •

* refactor: ๋ถˆ ํ•„์š”ํ•œ css ์ œ๊ฑฐ ๋ฐ ์ผ๊ด€์„ฑ์„ ์œ„ํ•œ ์ˆ˜์ •

* refactor: ๋ช…์„ธ isChecked์™€ checked ๋ถˆ์ผ์น˜๋กœ ์ธํ•œ ์ˆ˜์ •

* refactor(TravelogueDetailPage): extractId ์ ์šฉ

* refactor: mutate ๋„ค์ด๋ฐ, ์ƒ์ˆ˜ํ™”, ์œ ํ‹ธํ•จ์ˆ˜, Text ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* refactor(SearchFallback): ๊ฐ€์šด๋ฐ๋กœ ์˜ค๋„๋ก ์ •๋ ฌ

* refactor(SearchFallback): common์œผ๋กœ ๋ถ„๋ฆฌ

* feat(MainPage): ํƒœ๊ทธ ํ•„ํ„ฐ๋ง ๊ฒฐ๊ณผ ์—†์„ ์‹œ SearchFallback ๋ณด์—ฌ์ฃผ๋„๋ก ๊ตฌํ˜„

* refactor(MainPage): ํƒœ๊ทธ ๊ฐฏ์ˆ˜ ์„ค์ •์— ๊ด€ํ•œ ์„ค๋ช… ์ถ”๊ฐ€

* refactor(extractId): ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor: extractID ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(extractId): extractLastPath ์œ ํ‹ธํ™”์— ๋”ฐ๋ฅธ ๋ถ„๋ฆฌ

* fix(ModalBottomSheet): ์—๋‹ˆ๋ฉ”์ด์…˜ ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(SearchFallback): ui ์œ„์น˜ ์ˆ˜์ •

* refactor(TravelogueTabContent): negative margin-top ์ถ”๊ฐ€

* refactor(TravelPlanRegisterPage): ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก subText ์ถ”๊ฐ€

* refactor(TravelogueDetailPage): ๊ฐœํ–‰ ์ถ”๊ฐ€

* refactor(TravelogueRegisterPage): mutate ๋„ค์ด๋ฐ ์ˆ˜์ •

* [Feature] - ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ์— ์—ฌํ–‰ ๊ณ„ํš ์ž‘์„ฑ ์ถ”๊ฐ€ (#368)

* refactor(FloatingButton): ์—ฌํ–‰ ๊ณ„ํš ์ž‘์„ฑ ์ถ”๊ฐ€ ๋ฐ UI ์ˆ˜์ •

* refactor(FloatingButton): ์ž‘์„ฑ ํŽ˜์ด์ง€ ๋ฐ˜๋Œ€๋กœ ๊ฐ€๊ฒŒ๋” ๋˜์–ด์žˆ๋Š” ๊ฒƒ ์ˆ˜์ •

* refactor(zIndex): ์ˆ˜์ •

* refactor(FloatingButton): subButtonContainer gap ๋ฐ padding ์ˆ˜์ •

* [Feature] - required ๊ตฌํ˜„ (#361)

* feat(Input) : label ์†์„ฑ ์‚ญ์ œ

* feat(TextField) : TextField ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(TextField): TextField ์ปดํฌ๋„ŒํŠธ storybook ์ถ”๊ฐ€

* feat(TravelogueRegisterPage): TextField ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* feat(TravelPlanRegisterPage): TextField ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* style(TextField): style ์ˆ˜์ •

* refactor(TextField): cloneElement ๋Œ€์‹  renderProps๋ฅผ ์“ฐ๋„๋ก ์ˆ˜์ •

- cloneElement๋Š” legacy๋ผ๊ณ  ํ•จ

* style: isRequired ์‹ฌ๋ณผ ์ƒ‰์ƒ์„ ๋””์ž์ธ ํ† ํฐ์— ์ถ”๊ฐ€ ๋ฐ ์ ์šฉ

* refactor(TextField): props ์ˆ˜์ •

* refactor(ThumbnailUpload): id ๋ฐ›๋„๋ก ์ˆ˜์ •

- hiddenInput๊ณผ label์„ ์ •ํ™•ํ•˜๊ฒŒ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๊ธฐ ์œ„ํ•จ

* test(ThumbnailUpload): storybook์— ๋ณ€๊ฒฝ๋œ props ์ ์šฉ

* test(TextField): storybook์— id ์ถ”๊ฐ€

* refactor(TravelogueResisterPage,TravelPlanRegisterPage): TextFiled props์— renderProp ํ˜•์‹์œผ๋กœ ๋„˜๊ฒจ์ฃผ๋„๋ก ์ˆ˜์ •

* test(Header): Header ์ปดํฌ๋„ŒํŠธ์—์„œ IconButton์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฆฌํŒฉํ† ๋ง

* [Fix] - 4์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 1์ฐจ (์‹œ๋ชจ)  (#374)

* fix(MainPage): ์—ฌํ–‰๊ธฐ 1๊ฐœ์ผ ๋•Œ ๋ฉ”์ธ ํŽ˜์ด์ง€ ์Šคํƒ€์ผ ๊นจ์ง€๋Š” ๋ฌธ์ œ ์ˆ˜์ •

* fix(TransformBottomSheet): ํ™”์‚ดํ‘œ ์ด์™ธ์— ํด๋ฆญ์‹œ๋„ ๋‹ซ์น˜๊ฒŒ ์ˆ˜์ •

* fix(TravelogueDetailPage): ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์—ฌํ–‰๊ธฐ์˜ ๊ฒฝ์šฐ ๋ฐ”ํ…€์‹œํŠธ ์•ˆ๋ณด์ด๋„๋ก ์ˆ˜์ •

* fix(MyTravelPlans): ์—ฌํ–‰ ๊ณ„ํš 20์ž ๋„˜์–ด๊ฐ€๋ฉด ... ๋ณด์ด๋„๋ก ์ˆ˜์ •

* fix: ๋นˆ ๊ฐ’์˜ ๊ฒฝ์šฐ []๋‚˜ '' ๊ฐ’์œผ๋กœ ๋ณด๋‚ด๋„๋ก ์ˆ˜์ •

* fix(travelPlanRegisterPage): ํ…Œ์ŠคํŠธ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* fix(useInfiniteTravelogues): ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌํ•˜๋„๋ก isPaused ๋ฐ˜ํ™˜

* fix(MainPage): ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋ฐ ์„œ๋ฒ„ ์˜ค๋ฅ˜ ์‹œ alert ๋˜์ง€๋„๋ก ์ˆ˜์ •

* [Fix] - 4์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 1์ฐจ (์ง€๋‹ˆ) (#375)

* fix(useMultiImageUpload): ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ์ƒํƒœ์—์„œ ๋‹ค์ค‘ ์—…๋กœ๋“œ ์‹œ ๋ชจ๋‘ ์—…๋กœ๋“œ ๋˜๋Š” ์ด์Šˆ ์ˆ˜์ •

* fix(AccordionTrigger): IconButton์œผ๋กœ ๊ต์ฒด

svg๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ ๊ฒƒ์„ IconButton์œผ๋กœ ๊ต์ฒด

* fix: ์ข‹์•„์š” ํฌ๊ธฐ ๋ณ€๊ฒฝ

* refactor(PlaceTodoListItem): input์„ autofocus๋กœ ์ง€์ •

* fix(MyPage): ๋‹‰๋„ค์ž„ ๊ธ€์ž์ˆ˜ ์ œํ•œ ์ถ”๊ฐ€ ๋ฐ ๋‹‰๋„ค์ž„ ๋“ฑ๋ก ์‹œ ์ด์ „ ๋‹‰๋„ค์ž„์ด ๋ณด์—ฌ์ง€๋‹ค ํ˜„์žฌ ๋‹‰๋„ค์ž„์œผ๋กœ ๋ณด์—ฌ์ง€๋Š”  ๋ฌธ์ œ ์ˆ˜์ •

* fix(ShareModal): ๊ณต์œ  ๋ฒ„ํŠผ ๊ฐ„๊ฒฉ ์กฐ์ •

* fix: ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋กœ๊ทธ์ธ alert๊ฐ€ 2๋ฒˆ ๋œจ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ interceptor์˜ alert์™€ onError ์ฝœ๋ฐฑ์˜ alert๊ฐ€ ๊ฒน์ณ 2๋ฒˆ alert ๋œจ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(MyPage): input์ด 20์ž ๋„˜์–ด๊ฐ€๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(MyPage): ๋‹‰๋„ค์ž„ request query ํ•จ์ˆ˜ ๋„ค์ด๋ฐ ๊ฐœ์„ 

* refactor(ShareModal): spacing ์ ์šฉ

* fix: ci ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix: ci ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix: ci ๋ฌธ์ œ ํ•ด๊ฒฐ

* [Feature] - ํ”„๋ก ํŠธ์—”๋“œ dev, prod ๋ถ„๋ฆฌ ์ž‘์—… (#378)

* chore(package.json): babel ์„ค์ •์„ ์œ„ํ•œ ์˜์กด์„ฑ ์„ค์น˜

* chore: babel ๊ด€๋ จ config ์„ค์ • ์ถ”๊ฐ€

* chore: webpack dev, prod ๋ถ„๋ฆฌ

* chore(.gitignore): .env.local ํŒŒ์ผ ์ถ”๊ฐ€

* chore(.storybook/main): importSource ๋‚ด @emotion/react ์ถ”๊ฐ€

* chore: ci script dev, prod ๋ถ„๋ฆฌ

* chore(webpack.production): ๋ถˆํ•„์š”ํ•œ ๋ณ€์ˆ˜ ์ œ๊ฑฐ

* chore: ci ์Šคํฌ๋ฆฝํŠธ ์ˆ˜์ •

* chore: yarn.lock ์ˆ˜์ •

* fix: ci ๋ฌธ์ œ ํ•ด๊ฒฐ

* [Fix] - 4์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 1์ฐจ (๋ฆฌ๋ฒ„) (#376)

* feat(Input) : label ์†์„ฑ ์‚ญ์ œ

* feat(TextField) : TextField ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* test(TextField): TextField ์ปดํฌ๋„ŒํŠธ storybook ์ถ”๊ฐ€

* feat(TravelogueRegisterPage): TextField ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* feat(TravelPlanRegisterPage): TextField ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* style(TextField): style ์ˆ˜์ •

* fix(Header): $isRightContentFull ์†์„ฑ์ด๋ฆ„ isRightContentFull๋กœ ์ˆ˜์ •

* feat(SearchHeader): SearchHeader์— Home ์•„์ด์ฝ˜ ๋ฒ„ํŠผ ์ถ”๊ฐ€

* test(Header): Header ์Šคํ† ๋ฆฌ๋ถ์— SearchHeader ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜

* fix(PlaceDetailCard): ์—ฌํ–‰์ง€ ์ด๋ฏธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ FallbackImage๋ฅผ ๋ณด์—ฌ์ฃผ๋„๋ก ์ˆ˜์ •

* test(PlaceDetailCard): PlaceDetailCard ์Šคํ† ๋ฆฌ๋ถ์— ๋“ฑ๋กํ•œ ์—ฌํ–‰์ง€ ์‚ฌ์ง„์ด ์—†๋Š” ๊ฒฝ์šฐ ์ถ”๊ฐ€

* fix(useInfiniteSearchTravelogues): ๋กœ๊ทธ์ธ ์•ˆํ•ด๋„ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •

* feat(TravelogueCard): TravelogueCard์—์„œ ์ œ๋ชฉ์ด 20์ž๋ณด๋‹ค ๊ธธ์–ด์งˆ ๊ฒฝ์šฐ (...)๋กœ ์ค„์ž„ ์ถ”๊ฐ€

* test(TravelogueCard): TravelogueCard ์Šคํ† ๋ฆฌ๋ถ์— ์ œ๋ชฉ์ด 20์ž๋ณด๋‹ค ๊ธธ์–ด์ง€๋Š” ๊ฒฝ์šฐ ์ถ”๊ฐ€

* fix(TravelogueResisterPage): ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก์‹œ ์—ฌํ–‰๊ธฐ ์žฅ์†Œ ์‚ฌ์ง„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ payload์— ๋นˆ ๋ฐฐ์—ด ๋ณด๋‚ด๊ธฐ ์ถ”๊ฐ€

* chore(TravelogueResisterPage): ํ•„์š”์—†๋Š” ์ฃผ์„ ์‚ญ์ œ

* feat: TextField ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* [Feature] - 404 NotFound ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#380)

* feat:404 NotFound ํŽ˜์ด์ง€ ๊ตฌํ˜„

* chore(TravelPlanRegisterPage): ์‚ฌ์šฉ๋˜์ง€์•Š๋Š” import ๊ตฌ๋ฌธ ์‚ญ์ œ

* fix(TravelogueEditPage,TravelPlanEditPage): label ์‚ญ์ œ

* refactor(ThumbnailUpload): id props๋ฅผ ์˜ต์…”๋„๋กœ ์ˆ˜์ •

* fix(TravelPlanRegisterPage): import๋˜์–ด์žˆ์ง€ ์•Š์€ ์ปดํฌ๋„ŒํŠธ import

* refactor: ๋ถˆํ•„์š”ํ•œ ๊ฒƒ ์ œ๊ฑฐ

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Fix] - ๋กœ๋”ฉ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐ ๋ฉ”์ธํŽ˜์ด์ง€, ๋กœ๊ทธ์ธ ์ฝœ๋ฐฑ ํŽ˜์ด์ง€ ์˜ค๋ฅ˜ ์ˆ˜์ • (#391)

* fix(useMultiImageUpload): ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ์ƒํƒœ์—์„œ ๋‹ค์ค‘ ์—…๋กœ๋“œ ์‹œ ๋ชจ๋‘ ์—…๋กœ๋“œ ๋˜๋Š” ์ด์Šˆ ์ˆ˜์ •

* fix(AccordionTrigger): IconButton์œผ๋กœ ๊ต์ฒด

svg๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ ๊ฒƒ์„ IconButton์œผ๋กœ ๊ต์ฒด

* fix: ์ข‹์•„์š” ํฌ๊ธฐ ๋ณ€๊ฒฝ

* refactor(PlaceTodoListItem): input์„ autofocus๋กœ ์ง€์ •

* fix(MyPage): ๋‹‰๋„ค์ž„ ๊ธ€์ž์ˆ˜ ์ œํ•œ ์ถ”๊ฐ€ ๋ฐ ๋‹‰๋„ค์ž„ ๋“ฑ๋ก ์‹œ ์ด์ „ ๋‹‰๋„ค์ž„์ด ๋ณด์—ฌ์ง€๋‹ค ํ˜„์žฌ ๋‹‰๋„ค์ž„์œผ๋กœ ๋ณด์—ฌ์ง€๋Š”  ๋ฌธ์ œ ์ˆ˜์ •

* fix(ShareModal): ๊ณต์œ  ๋ฒ„ํŠผ ๊ฐ„๊ฒฉ ์กฐ์ •

* fix: ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋กœ๊ทธ์ธ alert๊ฐ€ 2๋ฒˆ ๋œจ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ interceptor์˜ alert์™€ onError ์ฝœ๋ฐฑ์˜ alert๊ฐ€ ๊ฒน์ณ 2๋ฒˆ alert ๋œจ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(MainPage): ์—ฌํ–‰๊ธฐ 1๊ฐœ์ผ ๋•Œ ๋ฉ”์ธ ํŽ˜์ด์ง€ ์Šคํƒ€์ผ ๊นจ์ง€๋Š” ๋ฌธ์ œ ์ˆ˜์ •

* fix(TransformBottomSheet): ํ™”์‚ดํ‘œ ์ด์™ธ์— ํด๋ฆญ์‹œ๋„ ๋‹ซ์น˜๊ฒŒ ์ˆ˜์ •

* fix(TravelogueDetailPage): ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์—ฌํ–‰๊ธฐ์˜ ๊ฒฝ์šฐ ๋ฐ”ํ…€์‹œํŠธ ์•ˆ๋ณด์ด๋„๋ก ์ˆ˜์ •

* fix(MyTravelPlans): ์—ฌํ–‰ ๊ณ„ํš 20์ž ๋„˜์–ด๊ฐ€๋ฉด ... ๋ณด์ด๋„๋ก ์ˆ˜์ •

* fix: ๋นˆ ๊ฐ’์˜ ๊ฒฝ์šฐ []๋‚˜ '' ๊ฐ’์œผ๋กœ ๋ณด๋‚ด๋„๋ก ์ˆ˜์ •

* fix(MyPage): input์ด 20์ž ๋„˜์–ด๊ฐ€๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(travelPlanRegisterPage): ํ…Œ์ŠคํŠธ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* refactor(MyPage): ๋‹‰๋„ค์ž„ request query ํ•จ์ˆ˜ ๋„ค์ด๋ฐ ๊ฐœ์„ 

* refactor(ShareModal): spacing ์ ์šฉ

* fix(useInfiniteTravelogues): ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌํ•˜๋„๋ก isPaused ๋ฐ˜ํ™˜

* fix(MainPage): ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋ฐ ์„œ๋ฒ„ ์˜ค๋ฅ˜ ์‹œ alert ๋˜์ง€๋„๋ก ์ˆ˜์ •

* chore(gitignore): .ene.local ์ถ”๊ฐ€

* fix(LoginFallback): ์ค„๋ฐ”๋€Œ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(MainPage): ํœ‘ ๋ฉ˜ํŠธ ๋ฐ subTitle ๋ฉ”์‹œ์ง€ ๋„ˆ๋น„์— ๋”ฐ๋ผ ๋ณ€ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(LoginPage): text ์ปดํฌ๋„ŒํŠธ ์ ์šฉ ๋ฐ ์Šคํƒ€์ผ๋ง ์ˆ˜์ •

* refactor(KakaoCallbackPage): usePostKakaoLogin ํ›… ๋ถ„๋ฆฌ ๋ฐ ๋„คํŠธ์›Œํฌ ์—๋Ÿฌ ์ฒ˜๋ฆฌ

* fix(useTravelogueDays): ์ „ํ™˜์‹œ PhotoUrls ๋นˆ๊ฐ’์œผ๋กœ ์ธํ•œ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* refactor(TravelogueDeleteModal): isPending ์‹œ spinner ๋ณด์—ฌ์ฃผ๋„๋ก ์ˆ˜์ •

* refactor(TravelogueDetailPage): error ๋ฐ ๋กœ๋”ฉ ์ฒ˜๋ฆฌ

* fix: ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ ์—๋Ÿฌ ์‹œ์—๋„ ์Šค์ผˆ๋ ˆํ†ค์ด ๋ณด์—ฌ์ง€๋„๋ก ๋ณ€๊ฒฝ

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Fix] - ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜์ •, ๋งˆ์ดํŽ˜์ด์ง€, ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ ์—๋Ÿฌ ํ•ธ๋“ค๋ง (#393)

* feat(useInfiniteMyTravelogues,MyTravelogues): ๋‚ด ์—ฌํ–‰๊ธฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* feat(useInfiniteMyTravelogues,MyTravelogues) : ํ”„๋กœํ•„ ์ •๋ณด๋ฅผ ์ž˜ ๊ฐ€์ ธ์™€์•ผ ๋‚ด ์—ฌํ–‰๊ธฐ๋ฅผ fetchํ•˜๋„๋ก ๊ตฌํ˜„, error ํ•ธ๋“ค๋ง ์ถ”๊ฐ€

* feat(MyPage): ๋‚ด ํ”„๋กœํ•„ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ error ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

* feat(MyTravelPlans,useInfiniteMyTravelPlans): ๋‚ด ํ”„๋กœํ•„ ์ •๋ณด๋ฅผ ์ž˜ ๊ฐ€์ ธ์™€์•ผ ์—ฌํ–‰๊ณ„ํš fetchํ•˜๋„๋ก ์ˆ˜์ •

* feat(MyTravelPlan): ์ปค๋ฐ‹ ๋ˆ„๋ฝ ์ถ”๊ฐ€

* feat(TravelPlanEditPage): ํ™•์ธ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋ฉด alert์ฐฝ ๋œจ๋„๋ก ์ˆ˜์ •

* feat: ๊ฒ€์ƒ‰ ์—๋Ÿฌ์ฒ˜๋ฆฌ (๋„คํŠธ์›Œํฌ,์„œ๋ฒ„์˜ค๋ฅ˜)

* feat: Query client retry ํšŸ์ˆ˜ 0์œผ๋กœ ์ˆ˜์ •

* fix: ์˜คํƒ€ ์ˆ˜์ •

* [Fix] - ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก & ์ˆ˜์ •, ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก, ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€ ์˜ˆ์™ธ ๋ฐ ๋กœ๋”ฉ ์ฒ˜๋ฆฌ (#394)

* fix: ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก & ์ˆ˜์ • ํŽ˜์ด์ง€ ๋กœ๋”ฉ ๋ฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

* fix: ์—ฌํ–‰ ๊ณ„ํ˜ธ๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

* fix: ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

* [Fix] - 4์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 2์ฐจ (์‹œ๋ชจ) (#400)

* fix(FloatingButton): ์—ฌํ–‰ ๊ณ„ํš ์ž‘์„ฑ ๊ธ€์ž ์ž˜๋ฆฌ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(useTravelPlanDays): todos ๋นˆ ๋ฐฐ์—ด๋กœ ๋ณด๋‚ด๋„๋ก ์ˆ˜์ •

* refactor(Button): children ์œ„์น˜ ์œ ์—ฐํ•˜๊ฒŒ ๋ฐ›๋„๋ก ์ˆ˜์ •

* fix(modalBottomSheet): isPending ์‹œ spinner ๋ณด์—ฌ์ฃผ๋„๋ก ์ˆ˜์ •

* fix(debouncedTime): ๋””๋ฐ”์šด์Šค ์‹œ๊ฐ„ 10์ดˆ๋กœ ์ˆ˜์ •

* fix(Button): justify-content ์•ˆ ๋จน๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* [Fix] - 4์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 2์ฐจ (๋ฆฌ๋ฒ„) (#401)

* refactor(Box): Box ์ปดํฌ๋„ŒํŠธ props ์ˆ˜์ •

* feat(TravelPlansTabContent): ์ƒ์„ธ์ง€๋„ ๋ณด๊ธฐ ์ถ”๊ฐ€

* refactor(TravelogueCard): title์„ Text ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ์œผ๋กœ ์ˆ˜์ •ํ•˜์—ฌ ํ…์ŠคํŠธ ์œ„ ์งค๋ฆผ ํ˜„์ƒ ์ˆ˜์ •

* fix(useInfiniteSearchTravelogues): api ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜์ •

* refactor(ThumbnailUpload): ์ด๋ฏธ์ง€๊ฐ€ ๋“ฑ๋ก ์ค‘์ผ ๋•Œ ์Šคํ”ผ๋„ˆ๊ฐ€ ๋‚˜์˜ค๋„๋ก ๊ตฌํ˜„

* feat(TravelogueRegisterPage): ์ธ๋„ค์ผ ์—…๋กœ๋“œ ํ›„ ๋ณด์ด๋Š” ์‚ญ์ œ๋ฒ„ํŠผ ๊ตฌํ˜„

* test(ThumbnailUpload): ๋กœ๋”ฉ ์ค‘์ธ ThumbnailUpload storybook ์ถ”๊ฐ€

* feat(TravelogueRegisterPage): ์ธ๋„ค์ผ ํ•„์ˆ˜๊ฐ’์œผ๋กœ ์ˆ˜์ •

* refactor(ThumbnailUpload): ThumbnailUpload์—์„œ ์ด๋ฏธ์ง€๊ฐ€ change๋ ๋•Œ isLoading ๋ณ€ํ•˜๊ฒŒ ์ˆ˜์ •, border๋ณด์ด๋Š” ์กฐ๊ฑด ์ˆ˜์ •

* fix: ์ธ๋„ค์ผ TextField ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€๊ฒฝ

* fix(ThumbnailUpload): ์ค‘๋ณต๋œ z-index ์ œ๊ฑฐ

* fix: ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ text๊ฐ€ ์ด์ƒํ•˜๊ฒŒ ๋ณด์ด๋Š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

* fix: ์ธ๋„ค์ผ require ์•„๋‹Œ ๊ฑธ๋กœ ์ˆ˜์ •

---------

Co-authored-by: แ„‰แ…ฉแ†ซแ„Œแ…ตแ†ซแ„‹แ…งแ†ผ <[email protected]>

* [Fix] - 4์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 2์ฐจ (์ง€๋‹ˆ) (#402)

* fix: ๊ตฌ๊ธ€๋งต ๋งˆ์ปค ํด๋ฆญ ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ณ€๊ฒฝ

* fix: ๋งˆ์ดํŽ˜์ด์ง€ alert 2๋ฒˆ ๋œจ๋Š” ํ˜„์ƒ ๊ฐœ์„ 

* fix: ์—ฌํ–‰ ๊ณ„ํš ๋ณ€ํ™˜ ์‹œ todos๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ๋นˆ๋ฐฐ์—ด๋กœ ์ƒ์„ฑ

* fix: ๋กœ๊ทธ์•„์›ƒ ์ƒํƒœ์—์„œ  ์ข‹์•„์š” ๋ˆ„๋ฅผ ๋•Œ alert 2๋ฒˆ ๋œจ๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix: ์—ฌํ–‰ ๊ณ„ํš date๊ฐ€ ์ œ๋Œ€๋กœ ๋ณด์ด์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix: ๋‹ฌ ๋งˆ์ง€๋ง‰ ์ผ์„ ์‹œ์ž‘์ผ๋กœ ํ•  ๋•Œ ์—ฌํ–‰ ๊ณ„ํš Day ์•„์ฝ”๋””์–ธ ์ถ”๊ฐ€ ์‹œ ๋‹ค์Œ ๋‹ฌ๋กœ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(TravelPlanRegisterPage): subText ์ถ”๊ฐ€

* fix(MyPage): ๋‹‰๋„ค์ž„ ํ•œ๊ธ€๋กœ ์ž…๋ ฅ ์‹œ 21์ž๋กœ ์ž…๋ ฅ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix: to do ์ž…๋ ฅ ์‹œ 20์ž๋กœ ์ œํ•œ ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* fix: ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์—ฌํ–‰ ๊ณ„ํš ์‹œ ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* fix: ์—ฌํ–‰๊ธฐ ์ˆ˜์ • ํŽ˜์ด์ง€ ๋‚ด ์ธ๋„ค์ผ์ด ์—†์„ ๊ฒฝ์šฐ ๋””ํดํŠธ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œ ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* fix: ci ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix: ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€ ๋‚ด ์ž‘์„ฑ์ž ์•„๋‹Œ ๊ฒŒ์‹œ๋ฌผ ์ ‘๊ทผ ์‹œ alert๊ฐ€ 2๋ฒˆ ๋œจ๋Š” ํ˜„์ƒ ๊ฐœ์„  (#404)

* [Fix] - line height,shareModal ์ˆ˜์ • (#407)

* fix(shareModal): ์ž˜๋ชป๋œ ํ…์ŠคํŠธ ์ˆ˜์ •

* style(typography): line-height ์ˆ˜์ •

* v1.0.1

* [Feature] - e2e ํ…Œ์ŠคํŠธ ์ดˆ๊ธฐ ์„ค์ • ๋ฐ ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก, ๋กœ๊ทธ์ธ, ๋ฉ”์ธ ํŽ˜์ด์ง€ e2e ํ…Œ์ŠคํŠธ ๊ตฌํ˜„ (#412)

* chore: cypress & eslint-plugin-cypress ์˜์กด์„ฑ ์„ค์น˜

* chore: eslint-plugin-cypress ์„ค์ • ์ถ”๊ฐ€

* chore: cypress ์‚ฌ์ „ ์„ธํŒ… ์ถ”๊ฐ€

1. baseUrl ๋ฐ viewport ์„ค์ • ์ถ”๊ฐ€

2. root tsconfig.json ๋‚ด exclude ์˜ต์…˜์— cypress ์ถ”๊ฐ€(__tests__ ๋‚ด ํ…Œ์ŠคํŠธ๋“ค type ๋ณด์žฅ์„ ์œ„ํ•ด)

3. cypress ๊ด€๋ จ declaration ์„ค์ • ์ถ”๊ฐ€

4. cypress ๋‚ด๋ถ€ tsconfig.json ์ถ”๊ฐ€

5. e2e.ts ์ถ”๊ฐ€

* feat: ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ตฌํ˜„

* feat: ์นด์นด์˜ค ๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ตฌํ˜„

* feat: ๋ฉ”์ธ ํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ตฌํ˜„

* refactor(travelPlanRegister): path alias ์ ์šฉ

* chore: ci e2e ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

* fix: ci ์Šคํฌ๋ฆฝํŠธ ์ˆ˜์ •

ci ์Šคํฌ๋ฆฝํŠธ์—์„œ e2e ํ…Œ์ŠคํŠธ ์ œ๊ฑฐ(๋กœ์ปฌ ํ™˜๊ฒฝ๊ณผ ci ํ™˜๊ฒฝ์—์„œ์˜ ํ…Œ์ŠคํŠธ ์ฐจ์ด๋กœ ์ธํ•ด ์ผ๋‹จ ๋ณด๋ฅ˜)

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋ฆฌํŒฉํ„ฐ๋ง (#414)

* refactor: ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋‚ด ์ƒํƒœ ์ •๋ฆฌ

form, ui, server, authorization, router ์ƒํƒœ์— ๋งž๊ฒŒ ์ •๋ฆฌ

* chore: immer, use-immer ์˜์กด์„ฑ ์ถ”๊ฐ€

* refactor(useTravelPlanDays): use-immer๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ฝ”๋“œ ๋ฆฌํŒฉํ„ฐ๋ง

* refactor(useTravelPlanDays): travelPlanDays์— ๊ฒŒ์œผ๋ฅธ ์ดˆ๊ธฐํ™” ์ ์šฉ

* refactor(useTravelPlanDays): ์žฅ์†Œ ๋‚ด todo ์ถ”๊ฐ€ ์‹œ ๊ธฐ์กด todos์— ์ถ”๊ฐ€๋งŒ ํ•˜๋„๋ก ๋ณ€๊ฒฝ

1. ์—ฌํ–‰ ๋ณ€ํ™˜, ์ˆ˜์ •, ์ถ”๊ฐ€ ๋ชจ๋‘ todos๊ฐ€ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— todos ํ•„๋“œ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š์•„๋„ ๋˜์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ

* fix: ํฐํŠธ import path ์ˆ˜์ • (#429)

* [Feature] - kakao bundle lazy loading ์ ์šฉ (#430)

* refactor(index.html): ์นด์นด์˜ค sdk script body ํƒœ๊ทธ๋กœ ์ด๋™

* fix: kakao sdk defer ์ œ์™ธ

defer ์ถ”๊ฐ€๋กœ ์ธํ•ด ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์ œ๊ฑฐ

* [Feature] - ๋ฐ๋ชจ๋ฐ์ด ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜(์ง€๋‹ˆ) (#418)

* refactor(GoogleMapView): ์ฝ”๋“œ ๋ฆฌํŒฉํ„ฐ๋ง

* chore(package.json): test-e2e:run ์Šคํฌ๋ฆฝํŠธ ์ˆ˜์ •

chrome์ด ๊ธฐ๋ณธ ๋ธŒ๋ผ์šฐ์ €๋กœ ํ…Œ์ŠคํŠธ ๋˜๋„๋ก ์ˆ˜์ •

* test(travelPlanRegister): force click์œผ๋กœ ๋ณ€๊ฒฝ

* fix(useTravelPlanDays): todo๊ฐ€ ์ œ๋Œ€๋กœ ์‚ญ์ œ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(Input): ๋ชจ๋ฐ”์ผ ํ™”๋ฉด์—์„œ ํ™•๋Œ€๋˜๋Š” ํ˜„์ƒ ํ•ด๊ฒฐ

Input font-size๋ฅผ 16px๋กœ ๋ณ€๊ฒฝ

* refactor(Calendar): ์บ˜๋ฆฐ๋” ui์—์„œ ์ง€๋‚œ ๋‚ ์งœ์— ๋Œ€ํ•œ ๋ณ„๋„ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€

์ด์ „ or ๋‹ค์Œ ๋‹ฌ์— ๋Œ€ํ•œ ๋‚ ์งœ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ  ์˜ค๋Š˜ ๊ธฐ์ค€ ์ด์ „ ๋‚ ์งœ์— ๋Œ€ํ•ด gray text ์ฒ˜๋ฆฌ ๋ฐ disable ์ฒ˜๋ฆฌ ํ•˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(GoogleMapView): ๋ถˆํ•„์š”ํ•œ console ์ œ๊ฑฐ

* test(travelPlanRegister): ๋ถˆํ•„์š”ํ•œ only ์ œ๊ฑฐ

* [Feature] - webpack ์บ์‹œ ๋ฒ„์ŠคํŒ… ์„ค์ • (#447)

* refactor(webpack): ์บ์‹œ ๋ฒ„์ŠคํŒ… ์ ์šฉ

๋นŒ๋“œ ํ•  ๋•Œ๋งˆ๋‹ค ๋ฒˆ๋“ค ํŒŒ์ผ ์ด๋ฆ„์„ ๋ณ€๊ฒฝ ์‹œ์ผœ ์บ์‹œ ๋ฌดํšจํ™” ์‹œํ‚ค๋„๋ก ๋ณ€๊ฒฝ

* refactor(webpack): chunkFilename ์ œ๊ฑฐ

* refactor(webpack): asset๋“ค์— ๋Œ€ํ•œ ํŒŒ์ผ ๊ฒฝ๋กœ ๋ฐ ํ•ด์‹œ ๊ฐ’ ์„ค์ • ๋ณ€๊ฒฝ

1. assets ๋‚ด ์œ„์น˜ ์‹œํ‚ค๋„๋ก ๋ณ€๊ฒฝ

2. hash๋ฅผ contenthash๋กœ ์ง€์ •ํ•˜์—ฌ ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ hash ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋„๋ก ์ง€์ •

* [Feature] - ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… ์„ค์ • (#450)

* chore: webpack-bundle-analyzer ์˜์กด์„ฑ ์ถ”๊ฐ€

* refactor: ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… ์ ์šฉ

* refactor: ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ

์Šค์ผˆ๋ ˆํ†ค์ด ์—†๋Š” ํŽ˜์ด์ง€์ธ ๊ฒ€์ƒ‰ ์‹œ์ž‘ ํŽ˜์ด์ง€, ์—ฌํ–‰๊ธฐ & ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜์ •/๋“ฑ๋ก ํŽ˜์ด์ง€๋งŒ ์ ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ

* refactor: BundleAnalyzerPlugin ์ฃผ์„ ์ถ”๊ฐ€

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€ ์„ฑ๋Šฅ ์ตœ์ ํ™” (#453)

* refactor(GoogleMapLoadScript): LoadScript ์‚ฌ์šฉ ๋Œ€์‹  useJsApiLoader๋กœ ๋ณ€๊ฒฝ

* refactor(index.html): google map์— ๋Œ€ํ•œ preconnect ๋ฐ dns-prefetch ์˜ต์…˜ ๊ด€๋ จ link ํƒœ๊ทธ ์ถ”๊ฐ€

* refactor: ๋ถˆํ•„์š”ํ•œ ๋นˆ๋ฌธ์ž์—ด ์ œ๊ฑฐ

* [Feature] - Layout Shift ๊ฐœ์„  (#454)

* refactor(AccordionRoot): gap ๊ฐ’ ์ˆ˜์ •

* refactor(TravelogueRegisterPage): layout shift ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(TravelogueEditPage): layout shift ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(TravelPlanRegisterPage): layout shift ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(TravelPlanEditPage): layout shift ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(Input): count ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฏธ๋ฆฌ ๊ณต๊ฐ„ ์ฐจ์ง€ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(Input): input ๋‚ด๋ถ€์— ์žˆ๋˜ characterCount ๋ถ„๋ฆฌ

* test(Input): input ์†์„ฑ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ storybook ์†์„ฑ ์ˆ˜์ •

* [Feature] - ์ด๋ฏธ์ง€ ์ตœ์ ํ™” (#455)

* feat(resizeAndConvertImage): ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ฆˆ,ํฌ๋งท ๋ณ€ํ™˜ ํ•ด์ฃผ๋Š” util ํ•จ์ˆ˜ ๊ตฌํ˜„

* feat(TravelogueRegisterPage): ์ธ๋„ค์ผ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ์‹œ ๋ฆฌ์‚ฌ์ด์ฆˆ ๋ฐ ๋ณ€ํ™˜ํ•˜๋„๋ก ์ˆ˜์ •

* feat(useMultiImageUpload): ์—ฌํ–‰์žฅ์†Œ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ์‹œ ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ฆˆ ๋ฐ ๋ณ€ํ™˜ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(resizeAndConvertImage):  2 depth if๋ฌธ ๊ฐœ์„ 

* refactor(resizeAndConvertImage): ํ•จ์ˆ˜ ์ฑ…์ž„ ๋ถ„๋ฆฌ

* v1.1.0

* [Feature] - ๋ฐ๋ชจ๋ฐ์ด ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜(์‹œ๋ชจ) (#434)

* fix(FloatingButton): ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ ๊ทผ์ฒ˜ ํด๋ฆญ์ด๋ฒคํŠธ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(Chip): isSelected์— ๋”ฐ๋ผ textType ๋‹ฌ๋ผ์ง€๋Š” ์ฝ”๋“œ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ˆ˜์ •

* fix(useSearchPlaceHistory): history api๋ฅผ ์ด์šฉํ•˜์—ฌ ์žฅ์†Œ ๊ฒ€์ƒ‰ ์ดํ›„ ๋’ค๋กœ๊ฐ€๊ธฐ ํด๋ฆญ ์‹œ ํŽ˜์ด์ง€ ์ด๋™ํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(useSearchPlaceHistory): early return ์œผ๋กœ ์ˆ˜์ •

* refactor(MainPage): theme์œผ๋กœ ์ˆ˜์ •

* refactor(useTagSelection): ํ›…์—์„œ sortedTags ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(Chip): ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ์œ„ํ•œ ์ˆ˜์ •

* fix(TravelPlanDeleteModal): padding์— ๋”ฐ์˜ดํ‘œ ์ œ๊ฑฐ

* refactor(Modal): ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•œ ์ˆ˜์ •

* refactor(useBottomSheet): ์ดˆ๊ธฐ๊ฐ’ ๋ณ€๊ฒฝํ•˜์—ฌ modal ์ผ๊ด€์„ฑ์žˆ๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

* refactor(Modal): ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์—ฌ bottomSheet๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •

* refactor(DeleteModal): ์ถ”์ƒํ™”

* refactor(EditRegisterModalBottomSheet): ์ถ”์ƒํ™”

* refactor(ShareModal): Modal Props ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* refactor(FloatingButton): backdropLayout์œผ๋กœ ์ˆ˜์ •

* storybook(Modal): Modal ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ • ๋ฐ EditRegisterModalBottomSheet ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* feat(SingleSelectionTagModalBottomSheet): ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* storybook(Modal): SingleSelectionTagModalBottomSheet ์Šคํ† ๋ฆฌ๋ถ ๊ตฌํ˜„

* refactor(SingleSelectionTagModalBottom): ๋ถˆ ํ•„์š”ํ•œ props ์ œ๊ฑฐ

* refactor(Modal): ๋‹ซ์น  ๋•Œ๋„ ์—๋‹ˆ๋ฉ”์ด์…˜์„ ๋ณด์—ฌ์ฃผ๋„๋ก ์ˆ˜์ •

* refactor(SingleSelectionTagModalBottomSheet): ๋ฒ„ํŠผ ๋ผ๋ฒจ ์ˆ˜์ •

* refactor(useMultiSelectionTag): ๋„ค์ด๋ฐ ์ˆ˜์ •

* feat(useSingleSelectionTag): ํ›… ๊ตฌํ˜„

* feat(MainPage): ์ •๋ ฌ ๋ฐ ์—ฌํ–‰๊ธฐ๊ฐ„ ํ•„ํ„ฐ๋ง UI ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„

* fix(Chip): tag ์„ ํƒ์‹œ ์—๋‹ˆ๋ฉ”์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฒ„๊ทธ ๊ฐ™์•„ ๋ณด์ด๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(createInfiniteTravelogueHandler): ์ธ์ž ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* chore: yarn install

* refactor(TravelogueRegisterPage): ํƒœ๊ทธ ์—๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€

* refactor(useInfiniteTravelogues): filter param ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(TravelogueEditPage): ํƒœ๊ทธ ์—๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€

* refactor: ํƒœ๊ทธ ์ปจํ…Œ์ด๋„ˆ layoutShift ํ•ด๊ฒฐ

* refactor(TransformBottomSheet): UI ์ˆ˜์ • ๋ฐ ๋‚ด์šฉ bottom sheet์— ์˜ํ•ด ๊ฐ€๋ ค์ง€๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(MainPage): ์ƒ๋‹จ ํ•„ํ„ฐ๋ง ๋ถ€๋ถ„ ๋ ˆ์ด์•„์›ƒ ๊ณ ์ •

* refactor(DeleteModal): ๋ฐ˜๋ณต๋˜๋Š” ํ…์ŠคํŠธ ๋ถ€๋ถ„ ์ถ”์ƒํ™”

* refactor(Chip): ๊ฐ€๋…์„ฑ์„ ์œ„ํ•œ ์ˆ˜์ •

* refactor(TransformFooter): bottom sheet ์—์„œ ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(Modal): ์ถ”์ƒํ™”ํ•œ ๋ชจ๋‹ฌ๋“ค ๋ชจ๋‹ฌ ๋‚ด๋ถ€๋กœ ์˜ค๋„๋ก ํŒŒ์ผ ๊ตฌ์กฐ ์ˆ˜์ •

* refactor(Modal): props ๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(Modal): ์ค‘๋ณต๋œ ์†์„ฑ ์ œ๊ฑฐ

* refactor(useInfiniteTravelogues): param์— sort ์ถ”๊ฐ€

* refactor(MainPage): ์ƒ์ˆ˜ ๋ถ„๋ฆฌ

* refactor(useInfiniteTravelogues): ์ธ์ž๋ฅผ ๊ฐ์ฒด๋กœ ๋ฐ›๋„๋ก ์ˆ˜์ •

* feat(storage): sort, filtering local storage์— ์ €์žฅํ•ด์„œ ํŽ˜์ด์ง€ ์ด๋™์‹œ์—๋„ ๊ธฐ์–ตํ•˜๋„๋ก ์ˆ˜์ •

* [Feature] - ๋ฐ๋ชจ๋ฐ์ด ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜(๋ฆฌ๋ฒ„) (#444)

* feat(PlaceDetailCard): ์—ฌํ–‰๊ธฐ ์‚ฌ์ง„ ์—†์„ ๊ฒฝ์šฐ noImage์ด ์•„๋‹Œ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ๋‚˜์˜ค๋„๋ก ์ˆ˜์ •

* test(PlaceDetailCard): ์ด๋ฏธ์ง€ ์—†๋Š” ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ์˜ args ์ˆ˜์ •

* feat(getDaysAndNights): ์—ฌํ–‰์ผ์ž ํ…์ŠคํŠธ ์ƒ์„ฑ util ํ•จ์ˆ˜ ๊ตฌํ˜„

* refactor(TravelogueDetailPage,TravelPlanDetailPage): ์—ฌํ–‰ ์ผ์ž ๊ณ„์‚ฐ util ํ•จ์ˆ˜ ์‚ฌ์šฉ

* feat(useInitialTripTitle): ์—ฌํ–‰๊ธฐ,์—ฌํ–‰๊ณ„ํš ์ œ๋ชฉ ์ดˆ๊ธฐ๊ฐ’ ์ƒ์„ฑ ์ปค์Šคํ…€ ํ›… ๊ตฌํ˜„

* feat(TravelogueRegisterPage,useTravelPlanForm): ์—ฌํ–‰๊ธฐ,์—ฌํ–‰๊ณ„ํš ๋ณ€ํ™˜์‹œ ์ œ๋ชฉ default๊ฐ’ ์ œ๊ณต

* feat(usePreviousPage): ๋’ค๋กœ๊ฐ€๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํ›… ๊ตฌํ˜„

- ๊ทธ ์ „ํŽ˜์ด์ง€๊ฐ€ my ํŽ˜์ด์ง€์ด๊ณ  ํ˜„์žฌ ํŽ˜์ด์ง€๊ฐ€ login ํŽ˜์ด์ง€๋ฉด ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ˆ„๋ฅผ์‹œ ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋„๋ก ๊ตฌํ˜„

* chore(useInitialTripTitle): Trip์„ Travel๋กœ ์ˆ˜์ •

* feat(TravelogueRegisterPage): ์ œ๋ชฉ input์— placeholder ์ถ”๊ฐ€

* fix(useInitialTravelTitle): ์ „ํ™˜์‹œ์—๋งŒ default title์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ˆ˜์ •

* fix(interceptor): ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์ค‘์ด ์•„๋‹ ๋•Œ alert,๋ฆฌ๋‹ค๋ฆฌ๋ ‰ํŠธํ•˜๋„๋ก ์ˆ˜์ •

- ์ธ๊ฐ€ ์ธ์ฆ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€์—์„œ ๋กœ๊ทธ์•„์›ƒ ํ›„ ๋‹ค์‹œ ์ธ๊ฐ€ ์ธ์ฆ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€๋กœ ์ด๋™์‹œ ๋กœ๊ทธ์ธ ํ•˜๋ผ๋Š” alert์ฐฝ์ด 2๋ฒˆ ๋œจ๋Š” ์ด์Šˆ๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ, ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์ค‘์—๋Š” alert ๋ฐ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฅผ ํ•˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ ์ˆ˜์ •ํ•จ

* feat(queryKey): search ์ฟผ๋ฆฌํ‚ค์— searchType ์ถ”๊ฐ€

* feat(useInfiniteSearchTravelogue): ์—ฌํ–‰๊ธฐ ๊ฒ€์ƒ‰ param์— searchType ์ถ”๊ฐ€

* style(Tab): ํ…์ŠคํŠธ ์„ธ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ ๋ฐ theme ์‚ฌ์šฉ ๋ฆฌํŒฉํ† ๋ง

* refactor(TravelogueList): ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋ถ€๋ถ„์„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ

* feat(SearchPage): ๊ฒ€์ƒ‰ ํƒ€์ž… Tab ์ถ”๊ฐ€

* feat(getInitialTravelTitle): ์ œ๋ชฉ ์ดˆ๊ธฐ๊ฐ’์—์„œ ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ ์‚ญ์ œ

- ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„์„ ์‚ญ์ œํ•˜๋ฉด์„œ ํ›…์ด ์•„๋‹ˆ๊ฒŒ๋˜์–ด ํ•จ์ˆ˜์ด๋ฆ„์„ useInitialTravelTitle์—์„œ getInitialTravelTitle๋กœ ์ˆ˜์ •ํ•˜๊ณ  util ํด๋”๋กœ ์ด๋™ ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

* refactor(usePreviousPage): type์—์„œ interface๋กœ ์ˆ˜์ •

* refactor(usePreviousPage): ํ•„์š”์—†๋Š” state ์‚ญ์ œ ๋ฐ ๊ทธ ์ „ ํŽ˜์ด์ง€๋งŒ ์ €์žฅํ•˜๋„๋ก ์ˆ˜์ •

- ๊ทธ์ „ ํŽ˜์ด์ง€๋งŒ ์•Œ๋ฉด๋˜๋ฏ€๋กœ ๊ฐ์ฒด๋กœ ์ €์žฅํ•  ํ•„์š”๊ฐ€ ์—†๊ณ , ๊ทธ์ „ ํŽ˜์ด์ง€๋ฅผ state๋กœ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ์— ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

* fix(MainPage): ํ…Œ๊ทธ ํ•„ํ„ฐ๋ง ์Šคํฌ๋กค ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#460)

* [Fix] - ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ ํƒญ๋ฐ” width ์ˆ˜์ •, ์—ฌํ–‰๊ธฐ ์ˆ˜์ •ํŽ˜์ด์ง€์—์„œ ์ด๋ฏธ์ง€ ์ตœ์ ํ™” ์•ˆ๋จ  (#462)

* fix(SearchPage): ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€ ํƒญ๋ฐ” width ์ˆ˜์ •

* fix(TravelogueEditPage): ์—ฌํ–‰๊ธฐ ์ˆ˜์ •ํŽ˜์ด์ง€์—์„œ ์ธ๋„ค์ผ ์—…๋กœ๋“œ ์ตœ์ ํ™” ์ถ”๊ฐ€

* fix: ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€๋Š” ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…์„ ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ (#465)

* fix(NotFound): NotFound ๋ฒ„ํŠผ ํ…์ŠคํŠธ ์ˆ˜์ • (#473)

์ด์ „ ํŽ˜์ด์ง€๋กœ๋กœ ๋Œ์•„๊ฐ€๊ธฐ๋ฅผ ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ธฐ๋กœ ์ˆ˜์ •

* [Fix] - tag filter ๋ฐ sort localStorage key ๊ฐ’์ด ๊ณต์œ ๋˜๋Š” ํ˜„์ƒ ํ•ด๊ฒฐ ๋ฐ ํƒœ๊ทธ ๋ณ€๊ฒฝ์‹œ ์ตœ์ƒ๋‹จ์œผ๋กœ ์ด๋™ํ•˜๋„๋ก ์ˆ˜์ • (#474)

* fix(MainPage): ํ…Œ๊ทธ ํ•„ํ„ฐ๋ง ์Šคํฌ๋กค ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(MainPage): sort, filtering storageKey ๊ณต์œ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐ ํƒœ๊ทธ ๋ณ€๊ฒฝ์‹œ ์ œ์ผ ์ฒ˜์Œ ์ปจํ…ํŠธ ๋ณด์ด๋„๋ก ์ˆ˜์ •

* refactor(useMultiSelection): ์ฝ”๋“œ์ƒ ์–ด์ƒ‰ํ•œ ๋ถ€๋ถ„ ์ˆ˜์ •

* [Fix] - ์ƒ์„ธ๋ณด๊ธฐ์—์„œ ์ข‹์•„์š” ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ์ง€๋„ ์›€์ง์ด๋Š” ๋ฌธ์ œ & ์‚ฌ์šฉ์ž๊ฐ€ ์ง€๋„๋ฅผ ํ™•๋Œ€ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ (#478)

* fix(GoogleMapView): ์ƒ์„ธ๋ณด๊ธฐ์—์„œ ์ข‹์•„์š” ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ์ง€๋„ ์›€์ง์ด๋Š” ๋ฌธ์ œ & ์‚ฌ์šฉ์ž๊ฐ€ ์ง€๋„๋ฅผ ํ™•๋Œ€ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

onBoundsChanged callback ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  useEffect๋ฅผ ํ†ตํ•ด places๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋งˆ๋‹ค zoom level๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋ณ€๊ฒฝ

* refactor: ์—ฌํ–‰ ์žฅ์†Œ๊ฐ€ ํ•˜๋‚˜์ผ ๋•Œ zoom level ์กฐ์ •

zoom level์„ 9๋กœ ๋ณ€๊ฒฝ

* [Fix] - 5์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 1์ฐจ (๋ฆฌ๋ฒ„) (#479)

* fix(SearchPage): ํƒญ๋ฐ”๊ฐ€ ํ—ค๋” ๊ฐ€๋ฆฌ๋Š” ๋ฌธ์ œ ์ˆ˜์ •

* fix: ์ข‹์•„์š” ์ˆœ,์ตœ์‹  ์ˆœ ๋งž์ถค๋ฒ• ์ˆ˜์ •

* fix(Header): ๊ฒ€์ƒ‰์ฐฝ placeholder ์ˆ˜์ •

* [Fix] - 5์ฐจ ์Šคํ”„๋ฆฐํŠธ QA ๋ฐ˜์˜ 1์ฐจ (์‹œ๋ชจ) (#485)

* fix(MainPage): ํ…Œ๊ทธ ํ•„ํ„ฐ๋ง ์Šคํฌ๋กค ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

* fix(MainPage): sort, filtering storageKey ๊ณต์œ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐ ํƒœ๊ทธ ๋ณ€๊ฒฝ์‹œ ์ œ์ผ ์ฒ˜์Œ ์ปจํ…ํŠธ ๋ณด์ด๋„๋ก ์ˆ˜์ •

* refactor(useMultiSelection): ์ฝ”๋“œ์ƒ ์–ด์ƒ‰ํ•œ ๋ถ€๋ถ„ ์ˆ˜์ •

* fix: ์ „์ฒด๋ฅผ ๋ฌดํšจํ™”ํ•จ์œผ๋กœ ์ธํ•ด api์š”์ฒญ ์—ฌ๋Ÿฌ๋ฒˆ ๋‚˜๊ฐ€๋Š” ๊ฒƒ ์ˆ˜์ •

* v1.2.0

* [Refactor] - API ์š”์ฒญ ๋ฐ ์‘๋‹ต ๋ช…์„ธ ํ†ต์ผ (#508)

* refactor: edit ์‘๋‹ต ๋ช…์„ธ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* refactor: ๋“ฑ๋ก ํŽ˜์ด์ง€ ์‘๋‹ต ๋ช…์„ธ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* refactor: checked ๋ช…์„ธ์„œ ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ isChecked๋กœ ์ˆ˜์ •

* refactor: useLocation ๋Œ€์‹  useParams ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

* refactor(TravelPlanTodoItem): as ์ˆ˜์ •

* [Feature] - Immer์„ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ ๊ตฌ์กฐ ๊ฐœ์„   (#495)

* refactor(useTravelogueDays): immer์„ ํ™œ์šฉํ•œ ๋กœ์ง ๊ตฌ์กฐ ๊ฐœ์„ 

* refactor(useTravelPlanDays): transformTravelPlanDays ๋ฆฌํŒฉํ„ฐ๋ง

* refactor(travelTransform): ์—ฌํ–‰๊ธฐ ๋ณ€ํ™˜ ํƒ€์ž… ์ˆ˜์ •(TravelTransformDays)

* refactor: query ๋‚ด ์ค‘์ฒฉ ๊ฐ์ฒด ๊ตฌ์กฐ Immer๋กœ ๊ฐœ์„ 

* fix(GoogleMapLoadScript): ๊ตฌ๊ธ€๋งต์„ ํ•œ๊ตญ์–ด๋กœ ๋ฐ›์•„์˜ค๋„๋ก ์ˆ˜์ • (#488)

* [Feature] - ์—ฌํ–‰ ๊ณ„ํš & ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ ์‹œ scroll ์ตœ์ƒ๋‹จ์œผ๋กœ ์ด๋™ ๋˜๋„๋ก ๋ณ€๊ฒฝ  (#511)

* refactor(TravelogueDetailPage): ์—ฌํ–‰๊ธฐ ์ƒ์„ธ ํŽ˜์ด์ง€ ์ด๋™ ์‹œ ์ตœ์ƒ๋‹จ์œผ๋กœ ์Šคํฌ๋กค ๋˜๋„๋ก ๋ณ€๊ฒฝ

* refactor(TravelPlanDetailPage): ์—ฌํ–‰ ๊ณ„ํš ์ƒ์„ธ ํŽ˜์ด์ง€ ์ด๋™ ์‹œ ์ตœ์ƒ๋‹จ์œผ๋กœ ์Šคํฌ๋กค ๋˜๋„๋ก ๋ณ€๊ฒฝ

* [Feature] - ์—ฌํ–‰๊ธฐ & ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก/์ˆ˜์ • ํŽ˜์ด์ง€ ๋ฆฌํŒฉํ„ฐ๋ง (#520)

* refactor(useTravelogueDays): ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ํŽ˜์ด์ง€ default export๋กœ ๋ณ€๊ฒฝ

* refactor(useTravelogueForm): ์—ฌํ–‰๊ธฐ form์— ๋Œ€ํ•œ ์ฑ…์ž„์„ useTravelogueForm์œผ๋กœ ๋ถ„๋ฆฌ

1. ์—ฌํ–‰๊ธฐ ์ œ๋ชฉ์— ๋Œ€ํ•œ ์ฑ…์ž„์„ useTravelogueTitle๋กœ ๋ถ„๋ฆฌ

2. ์—ฌํ–‰๊ธฐ ์ธ๋„ค์ผ์— ๋Œ€ํ•œ ์ฑ…์ž„์„ useTravelogueThumbnail๋กœ ๋ถ„๋ฆฌ

3. ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก์— ๋Œ€ํ•œ ์ฑ…์ž„์„ useTravelogueRegister๋กœ ๋ถ„๋ฆฌ

4. useTravelogueForm ์ถ”๊ฐ€

* refactor(useMultiImageUpload): ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๋กœ์ง์— ๋Œ€ํ•œ ๋ฆฌํŒฉํ„ฐ๋ง

1. TravelogueDayAccordion๊ณผ TravelogueMultiImageUpload ๋‚ด isPaused ๋ฐ onRequestAddImage ์ œ๊ฑฐ

2. useImageUpload ๋‚ด props ํ˜•ํƒœ ๋ณ€๊ฒฝ ๋ฐ usePostUploadImages hook์„ ๋‚ด๋ถ€์— ์ถ”๊ฐ€

* refactor(TravelogueRegisterPage): ํŽ˜์ด์ง€ ๋ฆฌํŒฉํ„ฐ๋ง

form์— ๋Œ€ํ•œ ์ฑ…์ž„์„ useTravelogueForm์— ์œ„์ž„ํ•˜์—ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ปดํฌ๋„ŒํŠธ ๋‚ด ์ œ๊ฑฐ

* refactor(ThumbnailUpload): fileRef์™€ click ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ

* refactor: ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ redirect ์‹œํ‚ค๋Š” hook ๋ถ„๋ฆฌ

1. useAuthRedirect hook ๋ถ„๋ฆฌ

2. ํ•ด๋‹น hook์„ ์—ฌํ–‰๊ธฐ & ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋‚ด ์ ์šฉ

* refactor: useToggle ํ›…์„ ํ†ตํ•ด open, close ํ•˜๋„๋ก ๋ณ€๊ฒฝ

1. open, close์— ๋Œ€ํ•œ useToggle hook ์ถ”๊ฐ€

2. ํ•ด๋‹น hook์„ ์—ฌํ–‰๊ธฐ & ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก ํŽ˜์ด์ง€ ๋‚ด ์ ์šฉ

* refactor(travelTransform): TravelTransformPlace์˜ ํƒ€์ž…์„ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์œผ๋กœ ๊ฐœ์„ 

* refactor(TravelogueRegisterPage): useTravelogueForm ํ˜•ํƒœ ๋ณ€๊ฒฝ

1. useTravelogueForm ๋‚ด submit ํ•˜๋Š” ๋กœ์ง ์ œ๊ฑฐ(์ˆ˜์ • ํŽ˜์ด์ง€์—์„œ๋„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด)

2. useTravelogueFormState๋กœ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ

3. TravelogueRegisterPage ๋‚ด useTravelogueRegister ์œ„์น˜ ์‹œํ‚ค๋„๋ก ๋ณ€๊ฒฝ

* refactor(TravelogueEditPage): ์—ฌํ–‰๊ธฐ ์ˆ˜์ • ํŽ˜์ด์ง€ ๋ฆฌํŒฉํ„ฐ๋ง

1. useTravelogueFormState ์žฌ ์‚ฌ์šฉ

2. useTravelogueEdit ํ›… ๋ถ„๋ฆฌ(์—ฌํ–‰๊ธฐ ์ˆ˜์ • ์š”์ฒญ)

3. travelogue ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™”์— ๋Œ€ํ•œ hook ์ถ”๊ฐ€(useTravelogueInitialization)

4. ์ž‘์„ฑ์ž ์—ฌ๋ถ€ ํ™•์ธ hook ๋ถ„๋ฆฌ(useAuthorCheck)

5. useTravelogueTitle ๋‚ด onChangeTitle ๋งค๊ฐœ๋ณ€์ˆ˜ ์ˆ˜์ •

6. ์ธ๋„ค์ผ hook ๋‚ด ์ธ๋„ค์ผ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๋Š” ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€

* refactor(TravelPlanRegisterPage): ์—ฌํ–‰ ๊ณ„ํš ๋“ฑ๋ก์— ๋Œ€ํ•œ ์ฑ…์ž„ ๋ถ„๋ฆฌ

1. useTravelPlanRegister ํ›… ๋”ฐ๋กœ ๋ถ„๋ฆฌ

2. TravelPlanRegisterPage์— ๋ฐ˜์˜

* refactor(TravelPlanRegisterPage): ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜์ • ํŽ˜์ด์ง€ ๋ฆฌํŒฉํ„ฐ๋ง

1. ์—ฌํ–‰ ๊ณ„ํš ์ˆ˜์ •์— ๋Œ€ํ•œ ์ฑ…์ž„ ๋ถ„๋ฆฌ(useTravelPlanEdit)

2. ์—ฌํ–‰ ๊ณ„ํš ์ดˆ๊ธฐํ™” hook ๋ถ„๋ฆฌ

3. useTravelPlanFormState๋กœ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ

4. startDate์™€ title์— ๋Œ€ํ•œ ์ฑ…์ž„์„ ๊ฐ๊ฐ ๋ถ„๋ฆฌ

* refactor: useTravelPlanFormState, useTravelogueFormState ํด๋”๊ตฌ์กฐ ๋ณ€๊ฒฝ

* fix(useTravelogueFormState): ci ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor: on prefix๋ฅผ handle prefix๋กœ ๋ณ€๊ฒฝ

์ปดํฌ๋„ŒํŠธ props ์ด์™ธ ํ•ธ๋“ค๋Ÿฌ๋Š” handle prefix๋ฅผ ๋”ฐ๋ผ์•ผํ•˜๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ

* refactor(ThumbnailUpload): ๋ถˆํ•„์š”ํ•œ ์ œ๋„ค๋ฆญ ์ œ๊ฑฐ

* refactor(travelTransform): import ์‹œ type ์ถ”๊ฐ€

* refactor(ThumbnailUpload): ๋ถˆํ•„์š”ํ•œ props ๊ฐœํ–‰ ์ œ๊ฑฐ

* [Feature] - ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ˆ˜์ • ๊ธฐ๋Šฅ ๋ฐ ์—ฌํ–‰๊ธฐ ๋“ฑ๋ก ์‹œ ์—ฌํ–‰ ์žฅ์†Œ๋งˆ๋‹ค ๊ตญ๊ฐ€ ์ฝ”๋“œ ์ฃผ๋„๋ก ๊ตฌํ˜„ (#535)

* refactor(Drawer): ๊ธฐ์กด ํ—ค๋“œ์™€ ๋†’์ด ๋‹ฌ๋ผ ์„  ์œ„์น˜๊ฐ€ ๋‹ค๋ฅธ ๋ฌธ์ œ ๊ฐœ์„ 

* feat: ์žฅ์†Œ ํ•„ํ„ฐ๋ง์„ ์œ„ํ•˜์—ฌ ์žฅ์†Œ ๋“ฑ๋ก์‹œ countryCode๋ฅผ ๋ณด๋‚ด๋„๋ก ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor(AvatarCircle): props $๋„ค์ด๋ฐ ์ˆ˜์ •

* refactor(MyTravelogue):$ ์ œ๊ฑฐ์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* refactor(usePostUploadImages): resize ์™€ convert ์ฒ˜๋ฆฌ ๋‚ด๋ถ€์—์„œ ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(MainPage): div semantic ํƒœ๊ทธ์ธ button์œผ๋กœ ์ˆ˜์ •

* feat(ProfileImageEditModalBottomSheet): ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(usePutProfile): api ๋ช…์„ธ ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ patch๋ฅผ put์œผ๋กœ, imageUrl body ๊ฐ’์— ๋ถ€์—ฌ

* refactor(AvatarCircle): props ์œ ์—ฐํ•˜๊ฒŒ ์ˆ˜์ •

* feat(useMyPage): ํ›… ๊ตฌํ˜„

* feat(MyPage): ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ˆ˜์ • ๊ธฐ๋Šฅ ๊ตฌํ˜„

* refactor(MyPage): ๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ pr ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜์ •

* refactor(SearchPage): ๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ pr ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜์ •

* refactor(useMyPage): useToggle ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

* refactor(common): ๋ฐ˜๋ณต๋˜๋Š” ํƒ€์ž…PlaceInfo ํƒ€์ž…์œผ๋กœ ์„ ์–ธ ๋ฐ ์ˆ˜์ •

* refactor(constants): ์ƒ์ˆ˜๋“ค ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌ

* refactor(useMyPage): ์ฑ…์ž„์— ๋”ฐ๋ผ ๊ฐ๊ฐ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋ถ„๋ฆฌ

* refactor(constants): ์ƒ์ˆ˜ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌ

* refactor(usePostUploadImages): max width, height ๊ฐ’ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •

* refactor(usePostUploadImages): max width, height ๊ฐ’ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •

* refactor(useProfileInitialization): ์˜์กด์„ฑ ๋ฐฐ์—ด ์ถ”๊ฐ€

* refactor: useCallback์œผ๋กœ update ํ•จ์ˆ˜ ๊ฐ์‹ธ์ฃผ๋„๋ก ์ˆ˜์ •

* [Fix] - 6์ฐจ ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜(์‹œ๋ชจ) (#545)

* refactor(MyPage): ์ด๋ชจ์ง€ ์ถ”๊ฐ€๋กœ ์—ฌํ–‰ ๊ณ„ํš, ์—ฌํ–‰๊ธฐ ๊ตฌ๋ถ„ ๋ช…ํ™•ํžˆ ๋˜๋„๋ก ์ˆ˜์ •

* refactor(Detail): ์ „ํ™˜์ด๋ผ๋Š” ์šฉ์–ด ๋‚ฏ์„ค๋‹ค๋Š” ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜

* refactor(Chip): icon ์ปดํฌ๋„ŒํŠธ ํฌํ•จํ•˜๋„๋ก ์ถ”์ƒํ™”

* feat(useMultiSelectionTag): animationKey ๋„ค์ด๋ฐ ์ˆ˜์ • ๋ฐ reset ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(useSingleSelectionTag): animationKey ๋ฐ ๋ฆฌ์…‹ ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(MainPage): reset Button ๊ธฐ๋Šฅ ๊ตฌํ˜„

* feat(assets): ๋ฆฌ์…‹ ๋ฒ„ํŠผ, ์ •๋ ฌ ๋ฒ„ํŠผ ์•„์ด์ฝ˜ ์ถ”๊ฐ€

* refactor: ์ดˆ๊ธฐํ™” ์‹œ  localStorage๋„ ์ดˆ๊ธฐํ™” ํ•˜๋„๋ก ์ˆ˜์ •

* refactor(useTravelogueFormState): animation key ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ์ˆ˜์ •

* refactor: ์ „ํ™˜ ์šฉ์–ด ๋ณ€๊ฒฝ

* refactor: ์ด๋ชจ์ง€ ์‚ญ์ œ

* refactor(svg-icons): ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ

* refactor(MainPage): ์˜์กด์„ฑ ๋ฌธ์ œ ํ•ด๊ฒฐ

* refactor(MyPage): ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ˆ˜์ • ๋ชจ๋‹ฌ ํ…์ŠคํŠธ ์ˆ˜์ •

* [Feature] - ๋ฉ”์ธ ํŽ˜์ด์ง€, ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ์›น ์ ‘๊ทผ์„ฑ ๊ฐœ์„  (#529)

* refactor(Header): ํ—ค๋”์— ์‚ฌ์šฉ๋œ IconButton๋“ค์— aria-label ์ถ”๊ฐ€

* refactor(Drawer): button ํƒœ๊ทธ ์ค‘์ฒฉ ์‚ฌ์šฉ ์ˆ˜์ •

* chore(MainPage): ํ•„์š” ์—†๋Š” ๊ณต๋ฐฑ,ํƒœ๊ทธ ์‚ญ์ œ

* refactor(AvatarCircle): props ์ˆ˜์ •

* refactor(TravelogueCard): ์›น ์ ‘๊ทผ์„ฑ ๊ฐœ์„ 

- ์žฅ์‹ ์ด๋ฏธ์ง€์— alt ๋นˆ ๊ฐ’ ์ถ”๊ฐ€
- ์นด๋“œ ์ปดํฌ๋„ŒํŠธ ํƒœ๊ทธ๋ฅผ button ํƒœ๊ทธ๋กœ ์ˆ˜์ •
- aria-label ์ถ”๊ฐ€

* refactor(Chip): as props ์ถ”๊ฐ€

* style(FallbackImage): color contrast ๊ฐœ์„ 

* refactor(MainPage): Chip์„ button์œผ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •

* refactor(FloatingButton): ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ title ์ถ”๊ฐ€

* feat(FocusTrap): ํ‚ค๋ณด๋“œ ํŠธ๋žฉ hook ๊ตฌํ˜„

Co-Authored-By: jinyoung <[email protected]>

* refactor(Modal): createPortal ์œ„์น˜๋ฅผ #root์—์„œ body๋กœ ๋ณ€๊ฒฝ

* refactor(FocusTrap): onEscapeFocusTrap์„ ์˜ต์…”๋„๋กœ ์ˆ˜์ •

* feat(Header): ํ‚ค๋ณด๋“œ ํŠธ๋žฉ ์ ์šฉ

* refactor(Header): ์‹œ๋งจํ‹ฑ ํƒœ๊ทธ ์ˆ˜์ •

* feat(Drawer): esc๋กœ ๋‹ซ๊ธฐ ์ถ”๊ฐ€ ๋ฐ ์—ด๋ ค์žˆ์„ ๊ฒฝ์šฐ์—๋งŒ DrawerContainer๋ Œ๋”๋งํ•˜๋„๋ก ์ˆ˜์ •

- DrawerContainer๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ Œ๋”๋ง๋˜์–ด์žˆ์œผ๋ฉด ์ด๋•Œ๋ถ€ํ„ฐ ์ด๋ฏธ focusTrap๋„ ๊ฐ™์ด ๋ Œ๋”๋ง๋˜์–ด Drawer๊ฐ€ ์—ด๋ ค์žˆ์ง€ ์•Š์•„๋„ focus trap์ด Drawer content ๋‚ด๋ถ€์— ๊ฐ‡ํžˆ๋Š” ์ด์Šˆ๊ฐ€ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

* feat(FocusTrap): ์ฒซ๋ฒˆ์งธ ์š”์†Œ์— ์ž๋™ ํฌ์ปค์Šค ์‚ญ์ œ

* feat(Modal): ๋ชจ๋‹ฌ์— FocusTrap ์ ์šฉ

* feat(MainPage): ์‹œ๋งจํ‹ฑ ํƒœ๊ทธ ๊ฐœ์„ 

* feat(MainPage): ๋ชจ๋‹ฌ ์—ด๋ฆผ ๋‹ซํž˜ ์•Œ๋ฆผ ์ถ”๊ฐ€

* feat(removeEmojis): ์ด๋ชจ์ง€๋ฅผ ์ง€์šฐ๊ณ  string๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ์œ ํ‹ธ ํ•จ์ˆ˜ ์ถ”๊ฐ€

* refactor(TravelogueCard): removeEmojis ์œ ํ‹ธ ํ•จ์ˆ˜ ์‚ฌ์šฉ

* refactor(FloatingButton): ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ์— focus trap ์‚ฌ์šฉ

* style(FloatingButton): visual hidden ์Šคํƒ€์ผ ์ถ”๊ฐ€

* feat(VisuallyHidden): Visually hidden ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€

- ์›น ์ ‘๊ทผ์„ฑ ๊ฐœ์„ ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ณด์ด์ง€ ์•Š๋Š” ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

* feat(MainPage): ํƒœ๊ทธ ์„ ํƒ,ํ•ด์ œ์‹œ ์•Œ๋ฆผ ์ถ”๊ฐ€

* feat(MainPage): TravelogueCard ๋ฆฌ์ŠคํŠธ ์‹œ๋งจํ‹ฑ ํƒœ๊ทธ ๊ฐœ์„ 

* fix(TravelogueCard): aria-live ์†์„ฑ ์‚ญ์ œ

- ํ•„ํ„ฐ,์ •๋ ฌ๋”œ ๋•Œ ๋งˆ๋‹ค ๋ Œ๋”๋ง๋˜์–ด์žˆ๋Š” ๋ชจ๋“  ์นด๋“œ aria-label์ด ์ฝํžˆ๋Š” ์ด์Šˆ๊ฐ€ ์žˆ์–ด์„œ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค.

* feat(MainPage): ๋ชจ๋‹ฌ ์—ด/๋‹ซํž˜ ์•Œ๋ฆผ์— VisuallyHidden ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ

* refactor(Drawer): Trigger ์‹œ๋งจํ‹ฑ ํƒœ๊ทธ ๋ฐ props ์ˆ˜์ •

- โ€ฆ
  • Loading branch information
7 people authored Oct 25, 2024
1 parent 457a1b1 commit c7c1975
Show file tree
Hide file tree
Showing 11 changed files with 628 additions and 432 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@tanstack/react-query-devtools": "^5.51.1",
"axios": "^1.7.2",
"dotenv-webpack": "^8.1.0",
"heic2any": "^0.0.4",
"immer": "^10.1.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/pages/main/MainPage.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,18 @@ export const MainPageList = styled.li`
export const FetchButton = styled.button`
position: fixed;
bottom: 0;
left: 0;
left: -10rem;
z-index: ${({ theme }) => theme.zIndex.floating};
padding: ${({ theme }) => theme.spacing.xs};
background-color: ${PRIMITIVE_COLORS.black};
color: ${PRIMITIVE_COLORS.white};
transform: translateY(100%);
transition: transform 0.3s;
transform: translateX(0);
&:focus {
transform: translateY(0);
transform: translateX(10rem);
transition: transform 0.3s;
}
`;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useNavigate } from "react-router-dom";
import { useBeforeUnload, useNavigate } from "react-router-dom";

import {
Accordion,
Expand All @@ -18,6 +18,7 @@ import { useTravelPlanInitialization } from "@components/pages/travelPlanEdit/ho
import TravelPlanDayAccordion from "@components/pages/travelPlanRegister/TravelPlanDayAccordion/TravelPlanDayAccordion";

import useTravelPlanFormState from "@hooks/pages/useTravelPlanFormState/useTravelPlanFormState";
import usePrompt from "@hooks/usePrompt";
import useToggle from "@hooks/useToggle";

import { ERROR_MESSAGE_MAP } from "@constants/errorMessage";
Expand Down Expand Up @@ -69,6 +70,15 @@ const TravelPlanEditPage = () => {

const navigate = useNavigate();

usePrompt({
message: "์‚ฌ์ดํŠธ์—์„œ ๋‚˜๊ฐ€์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?",
when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
});

useBeforeUnload((event) => {
event.preventDefault();
});

if (status === "error") {
const errorMessage =
error?.message === ERROR_MESSAGE_MAP.api.travelPlanOnlyWriter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useBeforeUnload } from "react-router-dom";

import { useTravelTransformDetailContext } from "@contexts/TravelTransformDetailProvider";

import {
Expand All @@ -18,6 +20,7 @@ import useTravelPlanRegister from "@components/pages/travelPlanRegister/hooks/us

import useTravelPlanFormState from "@hooks/pages/useTravelPlanFormState/useTravelPlanFormState";
import useAuthRedirect from "@hooks/useAuthRedirect";
import usePrompt from "@hooks/usePrompt";
import useToggle from "@hooks/useToggle";

import { CYPRESS_DATA_MAP } from "@constants/cypress";
Expand Down Expand Up @@ -69,8 +72,22 @@ const TravelPlanRegisterPage = () => {
handleBottomSheetClose,
);

usePrompt({
message: "์‚ฌ์ดํŠธ์—์„œ ๋‚˜๊ฐ€์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?",
when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
});

useAuthRedirect();

usePrompt({
message: "์‚ฌ์ดํŠธ์—์„œ ๋‚˜๊ฐ€์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?",
when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
});

useBeforeUnload((event) => {
event.preventDefault();
});

return (
<>
<S.Layout>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useBeforeUnload } from "react-router-dom";

import {
Accordion,
Button,
Expand All @@ -18,6 +20,7 @@ import TravelogueDayAccordion from "@components/pages/travelogueRegister/Travelo

import useTravelogueFormState from "@hooks/pages/useTravelogueFormState/useTravelogueFormState";
import { useDragScroll } from "@hooks/useDragScroll";
import usePrompt from "@hooks/usePrompt";
import useToggle from "@hooks/useToggle";
import useUnmountAnimation from "@hooks/useUnmountAnimation";

Expand Down Expand Up @@ -78,6 +81,15 @@ const TravelogueEditPage = () => {
handleInitializeThumbnail,
});

usePrompt({
message: "์‚ฌ์ดํŠธ์—์„œ ๋‚˜๊ฐ€์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?",
when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
});

useBeforeUnload((event) => {
event.preventDefault();
});

return (
<>
<S.Layout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ interface ImageState {
isLoading: boolean;
}

const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25MB in bytes

export const useTravelogueMultiImageUpload = ({
dayIndex,
placeIndex,
Expand Down Expand Up @@ -71,18 +73,20 @@ export const useTravelogueMultiImageUpload = ({
};

const handleChangeImage = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (isPaused) {
alert(ERROR_MESSAGE_MAP.network);
return;
}

const files = Array.from(e.target.files as FileList);

if (imageStates.length + files.length > MAX_IMAGE_UPLOAD_COUNT) {
alert(ERROR_MESSAGE_MAP.imageUpload);
return;
}

const oversizedFile = files.find((file) => file.size > MAX_FILE_SIZE);

if (oversizedFile) {
alert(`ํŒŒ์ผ '${oversizedFile.name}'์ด 25MB ์ œํ•œ์„ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.`);
return;
}

try {
addLoadingImageStates(files);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useBeforeUnload } from "react-router-dom";

import { useTravelTransformDetailContext } from "@contexts/TravelTransformDetailProvider";

import {
Expand All @@ -20,6 +22,7 @@ import useTravelogueRegister from "@components/pages/travelogueRegister/hooks/us
import useTravelogueFormState from "@hooks/pages/useTravelogueFormState/useTravelogueFormState";
import useAuthRedirect from "@hooks/useAuthRedirect";
import { useDragScroll } from "@hooks/useDragScroll";
import usePrompt from "@hooks/usePrompt";
import useToggle from "@hooks/useToggle";

import { FORM_VALIDATIONS_MAP } from "@constants/formValidation";
Expand Down Expand Up @@ -57,6 +60,15 @@ const TravelogueRegisterPage = () => {
isEnabledForm,
} = useTravelogueFormState(transformDetail?.days ?? []);

usePrompt({
message: "์‚ฌ์ดํŠธ์—์„œ ๋‚˜๊ฐ€์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?",
when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
});

useBeforeUnload((event) => {
event.preventDefault();
});

const payload = {
title,
thumbnail: thumbnail || (process.env.DEFAULT_THUMBNAIL_IMAGE ?? ""),
Expand Down
28 changes: 22 additions & 6 deletions frontend/src/hooks/useModalControl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect } from 'react';
import usePressESC from '@hooks/usePressESC';
import { useEffect } from "react";

import usePressESC from "@hooks/usePressESC";

/**
* modal control์— ๊ด€ํ•œ ํ›…์ž…๋‹ˆ๋‹ค.
Expand All @@ -10,11 +11,26 @@ const useModalControl = <T extends (...args: unknown[]) => void>(isOpen: boolean
usePressESC(isOpen, onToggle);

useEffect(() => {
if (isOpen) document.body.style.overflow = 'hidden';
if (isOpen) {
const scrollY = window.scrollY;

document.body.style.position = "fixed";
document.body.style.width = "100%";
document.body.style.top = `-${scrollY}px`;
document.body.style.overflow = "hidden";

document.body.style.touchAction = "none";

return () => {
document.body.style.position = "";
document.body.style.width = "";
document.body.style.top = "";
document.body.style.overflow = "auto";
document.body.style.touchAction = "";

return () => {
document.body.style.overflow = 'auto';
};
window.scrollTo(0, scrollY);
};
}
}, [isOpen]);
};

Expand Down
25 changes: 25 additions & 0 deletions frontend/src/hooks/usePrompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useEffect } from "react";
import { BlockerFunction, useBlocker } from "react-router-dom";

const usePrompt = ({ when, message }: { when: boolean | BlockerFunction; message: string }) => {
const blocker = useBlocker(when);

useEffect(() => {
if (blocker.state === "blocked") {
const proceed = window.confirm(message);
if (proceed) {
setTimeout(blocker.proceed, 0);
} else {
blocker.reset();
}
}
}, [blocker, message]);

useEffect(() => {
if (blocker.state === "blocked" && !when) {
blocker.reset();
}
}, [blocker, when]);
};

export default usePrompt;
51 changes: 36 additions & 15 deletions frontend/src/utils/resizeAndConvertImage.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
import heic2any from "heic2any";

import { ERROR_MESSAGE_MAP } from "@constants/errorMessage";
import { MAX_HEIGHT, MAX_WIDTH } from "@constants/resize";

const loadImageFromFile = (file: File): Promise<HTMLImageElement> => {
const loadImageFromFile = async (file: File): Promise<HTMLImageElement> => {
let processedFile = file;
if (file.type === "image/heic" || file.type === "image/heif") {
try {
const blob = await heic2any({
blob: file,
toType: "image/jpeg",
quality: 0.8,
});

processedFile = new File(
[Array.isArray(blob) ? blob[0] : blob],
file.name.replace(/\.heic$/i, ".jpg"),
{ type: "image/jpeg" },
);
} catch (error) {
throw new Error(`HEIC ์ด๋ฏธ์ง€๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ ์‹คํŒจ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.`);
}
}

return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = (error) => reject(error);
img.src = URL.createObjectURL(file);
img.onerror = () => {
reject(
new Error(`์ด๋ฆ„ - ${file.name}, ํƒ€์ž… - ${file.type}์ธ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๋Š”๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.`),
);
};
img.src = URL.createObjectURL(processedFile);
});
};

Expand Down Expand Up @@ -41,20 +66,15 @@ const resizeImage = (
const convertCanvasToBlob = (
canvas: HTMLCanvasElement,
format: string = "image/webp",
quality: number = 0.8,
): Promise<Blob> => {
return new Promise((resolve, reject) => {
canvas.toBlob(
(blob) => {
if (blob) {
resolve(blob);
} else {
reject(new Error(ERROR_MESSAGE_MAP.imageConvert));
}
},
format,
quality,
);
canvas.toBlob((blob) => {
if (blob) {
resolve(blob);
} else {
reject(new Error(ERROR_MESSAGE_MAP.imageConvert));
}
}, format);
});
};

Expand Down Expand Up @@ -82,6 +102,7 @@ const resizeAndConvertImage = async (
const newFile = createFileFromBlob(blob, file.name); // 4. Blob์„ ํŒŒ์ผ๋กœ ๋ณ€ํ™˜
return newFile;
} catch (error) {
console.error(error);
throw new Error(ERROR_MESSAGE_MAP.imageConvert);
}
};
Expand Down
Loading

0 comments on commit c7c1975

Please sign in to comment.