diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..1f3debe6 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,38 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +commitish: main + +categories: + - title: '๐Ÿš€ Feat' + labels: + - '๐Ÿ’ก Feature' + - '๐ŸŽจ Style' + - '๐Ÿ”จ Refactor' + - title: '๐Ÿ› Fix' + labels: + - '๐Ÿ’ฅ Fix' + - '๐Ÿšจ HOTFIX' + - title: '๐Ÿงฐ Init' + labels: + - '๐Ÿš€ Deploy' + - '๐Ÿงน Chore' + - '๐Ÿค– CI/CD' + +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' + +version-resolver: + major: + labels: + - '๐Ÿš€ Major' + minor: + labels: + - '๐Ÿ›ฅ๏ธ Minor' + patch: + labels: + - '๐Ÿš˜ Patch' + default: ๐Ÿš˜ Patch + +template: | + ## โœจ Changes + $CHANGES diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 00000000..cdae45a9 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,21 @@ +name: Release Drafter + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + draft-release: + runs-on: ubuntu-latest + steps: + - name: Run Release Drafter + uses: release-drafter/release-drafter@v6 + with: + config-name: release-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_DRAFTER_GITHUB_TOKEN }} diff --git a/apps/client/src/pages/login-fallback/login-fallback-page.tsx b/apps/client/src/pages/login-fallback/login-fallback-page.tsx index 9b857333..b3a006cb 100644 --- a/apps/client/src/pages/login-fallback/login-fallback-page.tsx +++ b/apps/client/src/pages/login-fallback/login-fallback-page.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router'; import { useSocialLogin } from '@widgets/login-fallback/hooks/use-social-login'; diff --git a/apps/client/src/shared/types/schema.d.ts b/apps/client/src/shared/types/schema.d.ts index 0884a5eb..d62c02b7 100644 --- a/apps/client/src/shared/types/schema.d.ts +++ b/apps/client/src/shared/types/schema.d.ts @@ -56,6 +56,30 @@ export interface paths { patch?: never; trace?: never; }; + '/posts/{post-id}/likes': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * ๊ฒŒ์‹œ๊ธ€ ์ข‹์•„์š” ์ƒ์„ฑ + * @description ์œ ์ €๊ฐ€ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€์— ์ข‹์•„์š”๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + */ + post: operations['createPostLike']; + /** + * ๊ฒŒ์‹œ๊ธ€ ์ข‹์•„์š” ์‚ญ์ œ + * @description ์œ ์ €๊ฐ€ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€์— ์ƒ์„ฑํ–ˆ๋˜ ์ข‹์•„์š”๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. + */ + delete: operations['deletePostLike']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; '/posts/{post-id}/comments': { parameters: { query?: never; @@ -97,6 +121,47 @@ export interface paths { patch?: never; trace?: never; }; + '/oauth/kakao/logout': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** ๋กœ๊ทธ์•„์›ƒ */ + post: operations['logout']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/oauth/kakao/login': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * ์นด์นด์˜ค ๋กœ๊ทธ์ธ + * @description ์นด์นด์˜ค API๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค. + */ + get: operations['kakaoCallback_1']; + put?: never; + /** + * ์นด์นด์˜ค ๋กœ๊ทธ์ธ - POST + * @description ์นด์นด์˜ค API๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค. POST ์š”์ฒญ์„ ์‚ฌ์šฉํ•˜์—ฌ Body์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค. + */ + post: operations['kakaoCallback']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; '/insurances/reports': { parameters: { query?: never; @@ -117,6 +182,26 @@ export interface paths { patch?: never; trace?: never; }; + '/files/upload': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ API + * @description mediaType์„ ํ†ตํ•ด PresignedUrl์„ ๋ฐœ๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค. + */ + post: operations['createdUrls']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; '/users/me/report-summary': { parameters: { query?: never; @@ -257,26 +342,6 @@ export interface paths { patch?: never; trace?: never; }; - '/oauth/kakao/login': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * ์นด์นด์˜ค ๋กœ๊ทธ์ธ - * @description ์นด์นด์˜ค API๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค. - */ - get: operations['kakaoCallback']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; '/insurances/reports/{insurance-report-id}': { parameters: { query?: never; @@ -449,6 +514,15 @@ export interface components { */ postId?: number; }; + BaseResponseVoid: { + /** + * Format: int32 + * @example 200 + */ + code?: number; + message?: string; + data?: Record; + }; CommentCreateRequest: { /** * @description ๋Œ“๊ธ€ ๋‚ด์šฉ @@ -471,6 +545,40 @@ export interface components { /** @description ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ */ refreshToken?: string; }; + BaseResponseString: { + /** + * Format: int32 + * @example 200 + */ + code?: number; + message?: string; + data?: string; + }; + OAuthLoginRequest: { + code: string; + redirectUrl?: string; + }; + BaseResponseKaKaoLoginResponse: { + /** + * Format: int32 + * @example 200 + */ + code?: number; + message?: string; + data?: components['schemas']['KaKaoLoginResponse']; + }; + KaKaoLoginResponse: { + /** + * Format: int64 + * @description ์œ ์ € PK + * @example 1 + */ + userId?: number; + /** @description ์•ก์„ธ์Šค ํ† ํฐ */ + accessToken?: string; + /** @description ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ */ + refreshToken?: string; + }; InsuranceReportRequest: { /** * @description ์‹ค๋ช… @@ -593,6 +701,22 @@ export interface components { /** Format: uuid */ insuranceReportId?: string; }; + PresignedUrlRequest: { + /** @description ํŒŒ์ผ ํ˜•์‹ */ + mediaType?: string[]; + }; + BaseResponsePresignedUrlResponse: { + /** + * Format: int32 + * @example 200 + */ + code?: number; + message?: string; + data?: components['schemas']['PresignedUrlResponse']; + }; + PresignedUrlResponse: { + presignedUrls?: string[]; + }; BaseResponseInsuranceReportSummaryResponse: { /** * Format: int32 @@ -972,27 +1096,6 @@ export interface components { /** @description ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€ ์—ฌ๋ถ€ */ isLast?: boolean; }; - BaseResponseKaKaoLoginResponse: { - /** - * Format: int32 - * @example 200 - */ - code?: number; - message?: string; - data?: components['schemas']['KaKaoLoginResponse']; - }; - KaKaoLoginResponse: { - /** - * Format: int64 - * @description ์œ ์ € PK - * @example 1 - */ - userId?: number; - /** @description ์•ก์„ธ์Šค ํ† ํฐ */ - accessToken?: string; - /** @description ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ */ - refreshToken?: string; - }; BaseResponseInsuranceReportResponse: { /** * Format: int32 @@ -1035,7 +1138,13 @@ export interface components { }; SectionData: { additionalInfo?: string; - statuses?: components['schemas']['ShowCoverageStatus'][]; + resource?: string; + statuses?: components['schemas']['ShowCoverageStatusDetail'][]; + }; + ShowCoverageStatusDetail: { + target?: string; + status?: string; + queryParamValue?: string; }; BaseResponseSurgerySection: { /** @@ -1127,15 +1236,6 @@ export interface components { hyphenCase?: string; coverage?: components['schemas']['CompareCoverage']; }; - BaseResponseVoid: { - /** - * Format: int32 - * @example 200 - */ - code?: number; - message?: string; - data?: Record; - }; }; responses: never; parameters: never; @@ -1508,12 +1608,9 @@ export interface operations { }; }; }; - getComments: { + createPostLike: { parameters: { - query?: { - cursor?: number; - size?: number; - }; + query?: never; header?: never; path: { 'post-id': number; @@ -1528,7 +1625,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseSliceResponseCommentResponseLong']; + '*/*': components['schemas']['BaseResponseVoid']; }; }; 400: { @@ -1589,7 +1686,7 @@ export interface operations { }; }; }; - createComment: { + deletePostLike: { parameters: { query?: never; header?: never; @@ -1598,11 +1695,7 @@ export interface operations { }; cookie?: never; }; - requestBody: { - content: { - 'application/json': components['schemas']['CommentCreateRequest']; - }; - }; + requestBody?: never; responses: { /** @description OK */ 200: { @@ -1610,7 +1703,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponsePostCreateResponse']; + '*/*': components['schemas']['BaseResponseVoid']; }; }; 400: { @@ -1663,11 +1756,16 @@ export interface operations { }; }; }; - reissue: { + getComments: { parameters: { - query?: never; + query?: { + cursor?: number; + size?: number; + }; header?: never; - path?: never; + path: { + 'post-id': number; + }; cookie?: never; }; requestBody?: never; @@ -1678,7 +1776,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseTokenReissueResponse']; + '*/*': components['schemas']['BaseResponseSliceResponseCommentResponseLong']; }; }; 400: { @@ -1721,6 +1819,14 @@ export interface operations { 'application/json': unknown; }; }; + 409: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; 500: { headers: { [name: string]: unknown; @@ -1731,16 +1837,18 @@ export interface operations { }; }; }; - issueReport: { + createComment: { parameters: { query?: never; header?: never; - path?: never; + path: { + 'post-id': number; + }; cookie?: never; }; requestBody: { content: { - 'application/json': components['schemas']['InsuranceReportRequest']; + 'application/json': components['schemas']['CommentCreateRequest']; }; }; responses: { @@ -1750,7 +1858,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseIssueInsuranceReportResponse']; + '*/*': components['schemas']['BaseResponsePostCreateResponse']; }; }; 400: { @@ -1803,7 +1911,7 @@ export interface operations { }; }; }; - getMyLastInsuranceReportSummary: { + reissue: { parameters: { query?: never; header?: never; @@ -1818,7 +1926,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseInsuranceReportSummaryResponse']; + '*/*': components['schemas']['BaseResponseTokenReissueResponse']; }; }; 400: { @@ -1871,11 +1979,10 @@ export interface operations { }; }; }; - getMyPosts: { + logout: { parameters: { query?: { - cursorId?: number; - size?: number; + 'redirect-url'?: string; }; header?: never; path?: never; @@ -1889,9 +1996,10 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseSliceResponseMyPostSummaryResponseLong']; + '*/*': components['schemas']['BaseResponseString']; }; }; + /** @description ๊ฒฝ๋กœ ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. */ 400: { headers: { [name: string]: unknown; @@ -1900,6 +2008,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์œ ํšจํ•˜์ง€ ์•Š์€ JWT์ž…๋‹ˆ๋‹ค. */ 401: { headers: { [name: string]: unknown; @@ -1908,6 +2017,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. */ 403: { headers: { [name: string]: unknown; @@ -1916,6 +2026,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์ง€์›ํ•˜์ง€ ์•Š๋Š” URL์ž…๋‹ˆ๋‹ค. */ 404: { headers: { [name: string]: unknown; @@ -1924,6 +2035,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์œ ํšจํ•˜์ง€ ์•Š์€ Http ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. */ 405: { headers: { [name: string]: unknown; @@ -1932,6 +2044,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์™ธ๋ถ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. */ 500: { headers: { [name: string]: unknown; @@ -1942,11 +2055,11 @@ export interface operations { }; }; }; - getMyComments: { + kakaoCallback_1: { parameters: { - query?: { - cursorId?: number; - size?: number; + query: { + code: string; + 'redirect-url'?: string; }; header?: never; path?: never; @@ -1960,7 +2073,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseSliceResponseMyCommentSummaryResponseLong']; + '*/*': components['schemas']['BaseResponseKaKaoLoginResponse']; }; }; 400: { @@ -2013,14 +2126,18 @@ export interface operations { }; }; }; - getInfo: { + kakaoCallback: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + 'application/json': components['schemas']['OAuthLoginRequest']; + }; + }; responses: { /** @description OK */ 200: { @@ -2028,7 +2145,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseUserProfileResponse']; + '*/*': components['schemas']['BaseResponseKaKaoLoginResponse']; }; }; 400: { @@ -2081,14 +2198,18 @@ export interface operations { }; }; }; - getJobs: { + issueReport: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + 'application/json': components['schemas']['InsuranceReportRequest']; + }; + }; responses: { /** @description OK */ 200: { @@ -2096,10 +2217,9 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseJobResponses']; + '*/*': components['schemas']['BaseResponseIssueInsuranceReportResponse']; }; }; - /** @description ๊ฒฝ๋กœ ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. */ 400: { headers: { [name: string]: unknown; @@ -2108,7 +2228,6 @@ export interface operations { 'application/json': unknown; }; }; - /** @description ์œ ํšจํ•˜์ง€ ์•Š์€ JWT์ž…๋‹ˆ๋‹ค. */ 401: { headers: { [name: string]: unknown; @@ -2117,7 +2236,6 @@ export interface operations { 'application/json': unknown; }; }; - /** @description ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. */ 403: { headers: { [name: string]: unknown; @@ -2126,7 +2244,6 @@ export interface operations { 'application/json': unknown; }; }; - /** @description ์ง€์›ํ•˜์ง€ ์•Š๋Š” URL์ž…๋‹ˆ๋‹ค. */ 404: { headers: { [name: string]: unknown; @@ -2135,7 +2252,6 @@ export interface operations { 'application/json': unknown; }; }; - /** @description ์œ ํšจํ•˜์ง€ ์•Š์€ Http ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. */ 405: { headers: { [name: string]: unknown; @@ -2144,7 +2260,6 @@ export interface operations { 'application/json': unknown; }; }; - /** @description ์™ธ๋ถ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. */ 500: { headers: { [name: string]: unknown; @@ -2155,7 +2270,79 @@ export interface operations { }; }; }; - getDiagnosedDisease: { + createdUrls: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['PresignedUrlRequest']; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + '*/*': components['schemas']['BaseResponsePresignedUrlResponse']; + }; + }; + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 405: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + }; + }; + getMyLastInsuranceReportSummary: { parameters: { query?: never; header?: never; @@ -2170,7 +2357,285 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseDiagnosedDiseaseResponses']; + '*/*': components['schemas']['BaseResponseInsuranceReportSummaryResponse']; + }; + }; + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 405: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + }; + }; + getMyPosts: { + parameters: { + query?: { + cursorId?: number; + size?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + '*/*': components['schemas']['BaseResponseSliceResponseMyPostSummaryResponseLong']; + }; + }; + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 405: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + }; + }; + getMyComments: { + parameters: { + query?: { + cursorId?: number; + size?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + '*/*': components['schemas']['BaseResponseSliceResponseMyCommentSummaryResponseLong']; + }; + }; + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 405: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + }; + }; + getInfo: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + '*/*': components['schemas']['BaseResponseUserProfileResponse']; + }; + }; + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 405: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': unknown; + }; + }; + }; + }; + getJobs: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + '*/*': components['schemas']['BaseResponseJobResponses']; }; }; /** @description ๊ฒฝ๋กœ ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. */ @@ -2229,7 +2694,7 @@ export interface operations { }; }; }; - getCoverageSelect: { + getDiagnosedDisease: { parameters: { query?: never; header?: never; @@ -2244,7 +2709,7 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseCoveragePreferenceResponses']; + '*/*': components['schemas']['BaseResponseDiagnosedDiseaseResponses']; }; }; /** @description ๊ฒฝ๋กœ ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. */ @@ -2303,11 +2768,9 @@ export interface operations { }; }; }; - kakaoCallback: { + getCoverageSelect: { parameters: { - query: { - code: string; - }; + query?: never; header?: never; path?: never; cookie?: never; @@ -2320,9 +2783,10 @@ export interface operations { [name: string]: unknown; }; content: { - '*/*': components['schemas']['BaseResponseKaKaoLoginResponse']; + '*/*': components['schemas']['BaseResponseCoveragePreferenceResponses']; }; }; + /** @description ๊ฒฝ๋กœ ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. */ 400: { headers: { [name: string]: unknown; @@ -2331,6 +2795,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์œ ํšจํ•˜์ง€ ์•Š์€ JWT์ž…๋‹ˆ๋‹ค. */ 401: { headers: { [name: string]: unknown; @@ -2339,6 +2804,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. */ 403: { headers: { [name: string]: unknown; @@ -2347,6 +2813,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์ง€์›ํ•˜์ง€ ์•Š๋Š” URL์ž…๋‹ˆ๋‹ค. */ 404: { headers: { [name: string]: unknown; @@ -2355,6 +2822,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์œ ํšจํ•˜์ง€ ์•Š์€ Http ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. */ 405: { headers: { [name: string]: unknown; @@ -2363,6 +2831,7 @@ export interface operations { 'application/json': unknown; }; }; + /** @description ์™ธ๋ถ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. */ 500: { headers: { [name: string]: unknown; diff --git a/apps/client/src/widgets/home/components/home-chip/home-chip.css.ts b/apps/client/src/widgets/home/components/home-card/home-card.css.ts similarity index 100% rename from apps/client/src/widgets/home/components/home-chip/home-chip.css.ts rename to apps/client/src/widgets/home/components/home-card/home-card.css.ts diff --git a/apps/client/src/widgets/home/components/home-chip/home-chip.tsx b/apps/client/src/widgets/home/components/home-card/home-card.tsx similarity index 83% rename from apps/client/src/widgets/home/components/home-chip/home-chip.tsx rename to apps/client/src/widgets/home/components/home-card/home-card.tsx index 73f6b729..08585e26 100644 --- a/apps/client/src/widgets/home/components/home-chip/home-chip.tsx +++ b/apps/client/src/widgets/home/components/home-card/home-card.tsx @@ -2,7 +2,7 @@ import { ReactNode } from 'react'; import { StatusType } from '@shared/types/type.ts'; -import * as styles from './home-chip.css.ts'; +import * as styles from './home-card.css.ts'; const statusMap = { ์ถฉ๋ถ„: 'enough', @@ -16,7 +16,7 @@ interface ChipProps { status?: StatusType; } -const HomeChip = ({ icon, title, status }: ChipProps) => { +const HomeCard = ({ icon, title, status }: ChipProps) => { const internalStatus = status ? statusMap[status] : undefined; return ( @@ -34,4 +34,4 @@ const HomeChip = ({ icon, title, status }: ChipProps) => { ); }; -export default HomeChip; +export default HomeCard; diff --git a/apps/client/src/widgets/home/components/info-section/info-section.tsx b/apps/client/src/widgets/home/components/info-section/info-section.tsx index 25fe1c71..77e58fb8 100644 --- a/apps/client/src/widgets/home/components/info-section/info-section.tsx +++ b/apps/client/src/widgets/home/components/info-section/info-section.tsx @@ -6,7 +6,7 @@ import { Swiper, SwiperSlide } from 'swiper/react'; import { Button } from '@bds/ui'; import { Icon } from '@bds/ui/icons'; -import HomeChip from '@widgets/home/components/home-chip/home-chip.tsx'; +import HomeCard from '@widgets/home/components/home-card/home-card.tsx'; import { homeChipConfig } from '@widgets/home/configs/home-chip-config.ts'; import InsuranceTitle from '@shared/components/insurance-title/insurance-title.tsx'; @@ -54,7 +54,7 @@ export const InfoSection = () => { > {homeChipConfig.map((chip, index) => ( - { return ( - } title={chip.title} status={chip.status as StatusType} @@ -124,7 +124,7 @@ export const RecommendedInfoSection = ({ const iconName = targetToIconMap.get(chip.target || ''); return ( - { const navigate = useNavigate(); type KakaoResponse = - paths['/oauth/kakao/login']['get']['responses']['200']['content']['*/*']['data']; + paths['/oauth/kakao/login']['post']['responses']['200']['content']['*/*']['data']; + + const getRedirectUrl = () => + import.meta.env.MODE === 'development' + ? appConfig.auth.kakaoLocalRedirectUrl + : appConfig.auth.kakaoProdRedirectUrl; const kakaoLogin = async (code: string) => { if (!code) { throw new Error('์ฝ”๋“œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.'); } + const redirectUrl = getRedirectUrl(); + try { const response = await ky - .get( - `${import.meta.env.VITE_API_BASE_URL}/oauth/kakao/login?code=${code}`, - ) + .post(`${appConfig.api.baseUrl}/oauth/kakao/login`, { + json: { code, redirectUrl }, + }) .json(); const { accessToken, refreshToken } = response.data; diff --git a/apps/client/src/widgets/report/components/accordion/accordion.tsx b/apps/client/src/widgets/report/components/accordion/accordion.tsx index d4760743..2a918c1f 100644 --- a/apps/client/src/widgets/report/components/accordion/accordion.tsx +++ b/apps/client/src/widgets/report/components/accordion/accordion.tsx @@ -2,9 +2,10 @@ import { ReactNode } from 'react'; import { Icon } from '@bds/ui/icons'; +import Chip from '@widgets/report/components/chip/chip.tsx'; + import { StatusType } from '@shared/types/type'; -import Chip from '../chip/chip'; import Title from '../title/title'; import { AccordionContextProvider } from './context-provider'; import { useAccordionContext } from './hooks/use-context'; diff --git a/apps/client/src/widgets/report/components/chip/chip.tsx b/apps/client/src/widgets/report/components/chip/chip.tsx index 8e4aa5ca..fe2c0406 100644 --- a/apps/client/src/widgets/report/components/chip/chip.tsx +++ b/apps/client/src/widgets/report/components/chip/chip.tsx @@ -1,6 +1,6 @@ import { StatusType } from '@shared/types/type'; -import * as styles from './chip.css'; +import * as styles from './chip.css.ts'; const statusMap = { ์ถฉ๋ถ„: 'enough', diff --git a/packages/bds-ui/src/components/index.ts b/packages/bds-ui/src/components/index.ts index 556ee69d..be983cba 100644 --- a/packages/bds-ui/src/components/index.ts +++ b/packages/bds-ui/src/components/index.ts @@ -6,6 +6,7 @@ export { default as Content } from './content/content'; export { default as Floating } from './floating/floating'; export { default as Indicator } from './indicator/indicator'; export { default as Input } from './input/input'; +export { default as LikeButton } from './like-button/like-button'; export { default as Modal } from './modal/modal'; export { default as ModalContainer } from './modal/modal-container'; export * from './modal/store/modal-store'; diff --git a/packages/bds-ui/src/components/like-button/like-button.css.ts b/packages/bds-ui/src/components/like-button/like-button.css.ts new file mode 100644 index 00000000..076a6741 --- /dev/null +++ b/packages/bds-ui/src/components/like-button/like-button.css.ts @@ -0,0 +1,22 @@ +import { recipe } from '@vanilla-extract/recipes'; + +import { themeVars } from '../../styles'; + +export const iconVariants = recipe({ + variants: { + isActive: { + true: { color: themeVars.color.error }, + false: { color: themeVars.color.gray600 }, + }, + size: { + sm: { + width: '1.6rem', + height: '1.6rem', + }, + md: { + width: '2.4rem', + height: '2.4rem', + }, + }, + }, +}); diff --git a/packages/bds-ui/src/components/like-button/like-button.stories.tsx b/packages/bds-ui/src/components/like-button/like-button.stories.tsx new file mode 100644 index 00000000..6e0a4603 --- /dev/null +++ b/packages/bds-ui/src/components/like-button/like-button.stories.tsx @@ -0,0 +1,139 @@ +import { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + +import LikeButton from './like-button'; + +const meta: Meta = { + title: 'Common/LikeButton', + component: LikeButton, + parameters: { + layout: 'centered', + docs: { + description: { + component: ` +**LikeButton** ์ปดํฌ๋„ŒํŠธ๋Š” '์ข‹์•„์š”' ํ† ๊ธ€์„ ์œ„ํ•œ ๋””์ž์ธ ์‹œ์Šคํ…œ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. +์ƒํƒœ๋Š” ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋„๋ก ์„ค๊ณ„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. + +## ์„ค๊ณ„ ๊ณ ๋ ค์‚ฌํ•ญ +- ์ ‘๊ทผ์„ฑ์„ ๊ณ ๋ คํ•ด ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค. +- ํฌ๊ธฐ๋Š” \`size\` variant('sm' | 'md')๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. sm: '1.6rem', md: '2.4rem' + +## ์ ‘๊ทผ์„ฑ +- \`aria-label\`์€ ๋™์ž‘(๋ˆŒ๋ €์„ ๋•Œ์˜ ํ–‰๋™)์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ \`ariaLabelWhenActive\` / \`ariaLabelWhenInActive\`๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +## Props ์š”์•ฝ +- **size**: ์•„์ด์ฝ˜ ํฌ๊ธฐ ํ”„๋ฆฌ์…‹ ('sm' | 'md') +- **isActive**: ํ˜„์žฌ ์ข‹์•„์š” ์ƒํƒœ (boolean) +- **onToggle?**: ํด๋ฆญ ์‹œ ํ˜ธ์ถœ๋˜๋Š” ์ฝœ๋ฐฑ (์ƒํƒœ ํ† ๊ธ€์€ ์ƒ์œ„์—์„œ ์ฒ˜๋ฆฌ; ๋งจ ์•„๋ž˜ \`Interactive\`์—์„œ ํ…Œ์ŠคํŠธ) +- **ariaLabelWhenActive?**: ํ™œ์„ฑํ™”(์ข‹์•„์š”๋จ) ์ƒํƒœ์ผ ๋•Œ ์Šคํฌ๋ฆฐ๋ฆฌ๋” ๋ผ๋ฒจ +- **ariaLabelWhenInActive?**: ๋น„ํ™œ์„ฑํ™”(์ข‹์•„์š” ์•ˆ๋จ) ์ƒํƒœ์ผ ๋•Œ ์Šคํฌ๋ฆฐ๋ฆฌ๋” ๋ผ๋ฒจ + `, + }, + }, + }, + argTypes: { + size: { + control: { type: 'radio' }, + options: ['sm', 'md'], + description: '์•„์ด์ฝ˜ ํฌ๊ธฐ ํ”„๋ฆฌ์…‹', + table: { type: { summary: "'sm' | 'md'" } }, + }, + isActive: { + control: { type: 'boolean' }, + description: '์ข‹์•„์š” ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.', + table: { type: { summary: 'boolean' } }, + }, + onToggle: { + description: + '๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ๋ณ€๊ฒฝ์€ ์ƒ์œ„์—์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.', + table: { type: { summary: '() => void' } }, + }, + ariaLabelWhenActive: { + control: { type: 'text' }, + description: 'ํ™œ์„ฑํ™”(์ข‹์•„์š”๋จ) ์ƒํƒœ์—์„œ์˜ aria-label.', + table: { type: { summary: 'string' } }, + }, + ariaLabelWhenInActive: { + control: { type: 'text' }, + description: '๋น„ํ™œ์„ฑ(์ข‹์•„์š” ์•ˆ๋จ) ์ƒํƒœ์—์„œ์˜ aria-label.', + table: { type: { summary: 'string' } }, + }, + }, + tags: ['autodocs'], +}; + +export default meta; + +type Story = StoryObj; + +// Storybook ์ „์šฉ Wrapper +function SizeWrapper({ + size, + children, +}: { + size: 'sm' | 'md'; + children: React.ReactNode; +}) { + const className = `sb-like-size-${size}`; + const css = ` + .${className} svg { + width: ${size === 'sm' ? '1.6rem' : '2.4rem'} !important; + height: ${size === 'sm' ? '1.6rem' : '2.4rem'} !important; + } + `; + return ( +
+ + {children} +
+ ); +} + +export const Default: Story = { + args: { + size: 'md', + isActive: false, + ariaLabelWhenActive: '์ข‹์•„์š” ์ทจ์†Œ', + ariaLabelWhenInActive: '์ข‹์•„์š”', + }, + render: (args) => ( + + + + ), +}; + +export const Liked: Story = { + args: { + size: 'md', + isActive: true, + ariaLabelWhenActive: '์ข‹์•„์š” ์ทจ์†Œ', + ariaLabelWhenInActive: '์ข‹์•„์š”', + }, + render: (args) => ( + + + + ), +}; + +export const Interactive: Story = { + args: { + size: 'sm', + isActive: false, + ariaLabelWhenActive: '์ข‹์•„์š” ์ทจ์†Œ', + ariaLabelWhenInActive: '์ข‹์•„์š”', + }, + render: (args) => { + const [liked, setLiked] = useState(Boolean(args.isActive)); + return ( + + setLiked(!liked)} + /> + + ); + }, +}; diff --git a/packages/bds-ui/src/components/like-button/like-button.tsx b/packages/bds-ui/src/components/like-button/like-button.tsx new file mode 100644 index 00000000..a8df38fa --- /dev/null +++ b/packages/bds-ui/src/components/like-button/like-button.tsx @@ -0,0 +1,35 @@ +import { Icon } from '@bds/ui/icons'; + +import { iconVariants } from './like-button.css'; + +interface LikeButtonProps { + size: 'sm' | 'md'; + onToggle?: () => void; + isActive: boolean; + ariaLabelWhenActive?: string; + ariaLabelWhenInActive?: string; +} + +const LikeButton = ({ + size, + onToggle, + isActive, + ariaLabelWhenActive, + ariaLabelWhenInActive, +}: LikeButtonProps) => { + return ( + + ); +}; + +export default LikeButton;