From 782f2fb7acb6bac8aa490f4f4f6aaf9f7557f630 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Mon, 2 Dec 2024 17:31:02 +0900 Subject: [PATCH 01/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EB=93=9C=EB=A1=AD?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EC=83=9D=EC=84=B1=20#47?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcSorting.tsx | 36 +++++++++++++++ src/components/drop-down/DropDown.test.tsx | 0 src/components/drop-down/DropDown.tsx | 0 .../drop-down/DroptDown.stories.tsx | 0 .../sorting-button/SortingButton.stories.tsx | 44 +++++++++++++++++++ .../sorting-button/SortingButton.test.tsx | 0 .../sorting-button/SortingButton.tsx | 25 +++++++++++ 7 files changed, 105 insertions(+) create mode 100644 public/icons/IcSorting.tsx create mode 100644 src/components/drop-down/DropDown.test.tsx create mode 100644 src/components/drop-down/DropDown.tsx create mode 100644 src/components/drop-down/DroptDown.stories.tsx create mode 100644 src/components/sorting-button/SortingButton.stories.tsx create mode 100644 src/components/sorting-button/SortingButton.test.tsx create mode 100644 src/components/sorting-button/SortingButton.tsx diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx new file mode 100644 index 00000000..c6f4d4b9 --- /dev/null +++ b/public/icons/IcSorting.tsx @@ -0,0 +1,36 @@ +import { SVGProps } from 'react'; + +interface IcSortingProps extends SVGProps { + width?: number; + height?: number; + isActive?: boolean; +} + +const TEXT_COLOR = { + default: '#111827', + active: '#F9FAFB', +}; + +function IcSorting({ + width = 20, + height = 14, + isActive = false, +}: IcSortingProps) { + return ( + + + + ); +} + +export default IcSorting; diff --git a/src/components/drop-down/DropDown.test.tsx b/src/components/drop-down/DropDown.test.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx new file mode 100644 index 00000000..b25cfb66 --- /dev/null +++ b/src/components/sorting-button/SortingButton.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import SortingButton from './SortingButton'; + +const meta = { + title: 'Components/SortingButton', + component: SortingButton, + parameters: { + componentSubtitle: '목록의 아이템들의 순서를 정렬하게 만드는 컴포넌트', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LargeDefault: Story = { + args: { + label: '마감 임박', + isActive: false, + isLarge: true, + }, +}; +export const LargeActive: Story = { + args: { + label: '마감 임박', + isActive: true, + isLarge: true, + }, +}; + +export const SmallDefault: Story = { + args: { + label: '마감 임박', + isActive: false, + isLarge: false, + }, +}; + +export const SmallActive: Story = { + args: { + label: '마감 임박', + isActive: true, + isLarge: false, + }, +}; diff --git a/src/components/sorting-button/SortingButton.test.tsx b/src/components/sorting-button/SortingButton.test.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx new file mode 100644 index 00000000..6067931d --- /dev/null +++ b/src/components/sorting-button/SortingButton.tsx @@ -0,0 +1,25 @@ +import IcSorting from '../../../public/icons/IcSorting'; + +interface SortingButtonProps { + label?: string; + isActive: boolean; + isLarge: boolean; +} +const COLOR = { + default: 'bg-gray-50 text-gray-900', + active: 'bg-gray-900 text-gray-50', +}; +function SortingButton({ label, isActive, isLarge }: SortingButtonProps) { + return ( + + ); +} + +export default SortingButton; From df51bb2a9ed862fe9e4424e42d8c4644d9c28490 Mon Sep 17 00:00:00 2001 From: sun <104830526+sunnwave@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:48:03 +0900 Subject: [PATCH 02/16] =?UTF-8?q?=E2=9C=85[Test]=20=EB=93=9C=EB=A1=AD?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20#48=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 드롭다운 스토리북 테스트코드 merge --- src/components/drop-down/DropDown.tsx | 36 +++++++++++++++++++ .../drop-down/DroptDown.stories.tsx | 32 +++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx index e69de29b..43c82807 100644 --- a/src/components/drop-down/DropDown.tsx +++ b/src/components/drop-down/DropDown.tsx @@ -0,0 +1,36 @@ +interface DropDownProps { + variant: 'navbar' | 'find' | 'profile' | 'review'; + size: 'navbar' | 'large' | 'small'; +} + +const VARIANTS = { + navbar: ['마이페이지', '로그아웃'], + find: ['마감임박 순', '가까운 모임 날짜 순'], + profile: ['최신순', '오래된 순'], + review: ['평점 높은 순', '평점 낮은 순'], +}; + +const SIZE = { + navbar: `w-[40px] h-[40px]`, + small: `w-[36px] h-[36px]`, + large: `w-[110px] h-[40px]`, +}; + +function DropDown({ variant, size }: DropDownProps) { + const itemList = VARIANTS[variant]; + + return ( +
+
    + + {itemList.map((item, index) => ( +
  • + {item} +
  • + ))} +
+
+ ); +} + +export default DropDown; diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx index e69de29b..4c8bee2c 100644 --- a/src/components/drop-down/DroptDown.stories.tsx +++ b/src/components/drop-down/DroptDown.stories.tsx @@ -0,0 +1,32 @@ +import { Meta, StoryObj } from '@storybook/react'; +import DropDown from './DropDown'; +import { Radio } from '@headlessui/react'; + +const meta = { + title: 'Components/DropDown', + component: DropDown, + parameters: { + componentSubtitle: + '드롭다운 컴포넌트. 정렬 기준을 보여줄 때, NavBar에서 프로필 이미지를 눌렀을 때 사용됨', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const NavBarLarge: Story = { + argTypes: { + variant: { + options: ['navbar', 'find', 'profile', 'review'], + control: { type: 'select' }, + }, + size: { + options: ['navbar', 'small', 'large'], + control: { type: 'radio' }, + }, + }, + args: { + variant: 'find', + size: 'large', + }, +}; From 8265ce935fc06036c86aa3d9f14407ffe64aa0a0 Mon Sep 17 00:00:00 2001 From: sun <104830526+sunnwave@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:43:44 +0900 Subject: [PATCH 03/16] =?UTF-8?q?=F0=9F=92=84[Design]=20DropDown=20UI=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✅[Test] 드롭다운 스토리북 테스트코드 구현 #48 * 💄[Design] rootlayout 상단 padding 추가 (#65) * ✨[Feat] 공통컴포넌트 button 구현 #11 (#37) * ✅[Test] 버튼 테스트 코드 작성 #11 * 📦[Chore] jest.config 수정 * 📦[Chore] tailwind-merge 설치 * ✨[Feat] 버튼 컴포넌트 생성 및 초기 디자인 설정 * 💄[Design] 버튼 기본 스타일 cursor-pointer로 설정 * ✅[Test] 스타일 테스트 추가 * ♻️[Refactor] Home 페이지 button 컴포넌트에 props 추가 * ♻️[Refactor] 타입 선언 type에서 interface로 변경 #11 * 💄[Design] 스토리북 코드 작성 #11 * 💄[Design] 최소 너비 설정 #11 * 📦[Chore] tailwind content 수정 #11 * 📦[Chore] tailwind content 수정 #11 * ♻️[Refactor] button props 변경 및 해당 스타일 설정 #11 * ♻️[Refactor] button props 변경 #11 * ✅[Test] 스타일 관련 테스트 코드 삭제 #11 * 💄[Design] 스토리북 args 수정 #11 * 💬[Comment] test 코드 주석 정리 #11 * ♻️[Refactor] 사이즈, 배경, 색상을 객체 리터럴로 변경 및 variant 추가 #11 * 📝[Docs] 스토리북 버튼 텍스트 및 이름 수정 #11 * ♻️[Refactor] 중복 색상 삭제 및 variantColor에 gray 추가 #11 * 🎨[Style] 상수 이름 영문 대문자 스네이크 표기법으로 변경 #11 * 🎨[Style] 깃 컨벤션 - 함수 표현식에서 함수 선언식으로 수정 #11 * 🔥[Remove] 초기 설정에 bookclub에 작성했던 button 삭제 #11 * ♻️[Refactor] 배경스타일 및 색상 variant 변경 #11 * 📝[Docs] 변경된 Button props명으로 스토리북 args 수정 #11 * ✅[Test] 변경된 props에 따른 테스트 코드 수정 #11 * 💄[Design] DropDown UI 구현#51 * ♻️[Refactor] variant에 filtering 추가. 드롭다운 아이템 리스트 props로 입력받도록 변경. variant에 따른 UI 변경 코드 리팩토링 #51 * 📦[Chore] ci 작업 범위 및 메시지 수정 (#53) * 💄[Design] navbar 프로필 이미지 추가 #51 * ♻️[Refactor] IcSorting color props로 입력받을 수 있도록 수정 #51 * ✨[Feat] WrittenReview, RatingDisplay 컴포넌트 생성 #38 (#49) * ✨[Feat] 평점 표시용 RatingIcon 컴포넌트 추가 #38 * 🔥[Remove] 초시 설정때 생성된 불필요한 Button2 폴더 삭제 #38 * ♻️[Refactor] RatingIcon heartColor에서 checked로 prop 변경 #38 * ✨[Feat] 평점 공통컴포넌트 생성 #38 * ✨[Feat] RatingDisplay 스토리북 작성 #38 * ✨[Feat] WrittenReview 공통 컴포넌트 생성 #38 * ✨[Feat] WrittenReview 스토리북 작성 #38 * 🐛[Fix] WrittenReview 이미지 에러 처리 #38 * ✅[Test] WrittenReview 테스트 코드 작성 #38 * 🚚[Rename] rating에서 rating-display로 폴더명 수정 #38 * 💄[Design] 텍스트 dp font-medium 속성 추가 #38 * 💄[Design] small 사이즈 규격 변경, IcSorting svg path 변경 #51 * 💬[Comment] 주석 정리 #51 * ✅[Test] PR 등록을 위한 임시 테스트 코드 작성 #51 * ✅[Test] 임시 테스트코드 수정 #51 * 🔥[Remove] sorting-button 컴포넌트 폴더 삭제 #51 --------- Co-authored-by: cloud0406 <32586926+cloud0406@users.noreply.github.com> Co-authored-by: Minkyung Kim <97824352+wynter24@users.noreply.github.com> --- .github/workflows/chromatic.yml | 3 +- .github/workflows/{ci-develop.yml => ci.yml} | 34 ++++-- package-lock.json | 10 ++ package.json | 1 + public/icons/IcFiltering.tsx | 33 +++++ public/icons/IcSorting.tsx | 24 ++-- public/icons/RatingIcon.tsx | 32 +++++ public/icons/index.ts | 1 + public/images/profile.png | Bin 0 -> 7392 bytes src/app/bookclub/page.tsx | 8 +- src/app/layout.tsx | 2 +- src/components/button/Button.stories.ts | 8 +- src/components/button/Button.test.tsx | 37 +++++- src/components/button/Button.tsx | 49 +++++++- src/components/button2/Button2.stories.ts | 21 ---- src/components/button2/Button2.tsx | 7 -- src/components/drop-down/DropDown.test.tsx | 10 ++ src/components/drop-down/DropDown.tsx | 115 ++++++++++++++---- .../drop-down/DroptDown.stories.tsx | 10 +- .../rating-display/RatingDisplay.stories.tsx | 16 +++ .../rating-display/RatingDisplay.tsx | 23 ++++ .../sorting-button/SortingButton.stories.tsx | 44 ------- .../sorting-button/SortingButton.test.tsx | 0 .../sorting-button/SortingButton.tsx | 25 ---- .../written-review/WrittenReview.stories.tsx | 22 ++++ .../written-review/WrittenReview.test.tsx | 55 +++++++++ .../written-review/WrittenReview.tsx | 59 +++++++++ tailwind.config.ts | 7 +- 28 files changed, 496 insertions(+), 160 deletions(-) rename .github/workflows/{ci-develop.yml => ci.yml} (54%) create mode 100644 public/icons/IcFiltering.tsx create mode 100644 public/icons/RatingIcon.tsx create mode 100644 public/images/profile.png delete mode 100644 src/components/button2/Button2.stories.ts delete mode 100644 src/components/button2/Button2.tsx create mode 100644 src/components/rating-display/RatingDisplay.stories.tsx create mode 100644 src/components/rating-display/RatingDisplay.tsx delete mode 100644 src/components/sorting-button/SortingButton.stories.tsx delete mode 100644 src/components/sorting-button/SortingButton.test.tsx delete mode 100644 src/components/sorting-button/SortingButton.tsx create mode 100644 src/components/written-review/WrittenReview.stories.tsx create mode 100644 src/components/written-review/WrittenReview.test.tsx create mode 100644 src/components/written-review/WrittenReview.tsx diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index b4956881..10a5504a 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -8,7 +8,8 @@ on: - develop pull_request: branches: - - develop + - '**' + - '!main' # List of jobs jobs: diff --git a/.github/workflows/ci-develop.yml b/.github/workflows/ci.yml similarity index 54% rename from .github/workflows/ci-develop.yml rename to .github/workflows/ci.yml index e693a929..c239d990 100644 --- a/.github/workflows/ci-develop.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,17 @@ -name: CI for develop +name: CI on: pull_request: branches: - - develop + - '**' + - '!main' push: branches: - develop jobs: - ci-develop: - name: Lint, Test, and Build (develop) + ci: + name: Lint, Test, and Build runs-on: ubuntu-latest strategy: matrix: @@ -40,7 +41,7 @@ jobs: run: npm run build-storybook notify-discord: - needs: ci-develop + needs: ci runs-on: ubuntu-latest if: success() steps: @@ -51,14 +52,33 @@ jobs: { "embeds": [ { - "title": "🎉 develop 브랜치 알림", - "description": "${{ github.event_name == 'pull_request' && '새로운 PR이 성공적으로 등록되었습니다!' || 'Push가 성공적으로 완료되었습니다!' }}", + "title": "${{ + format('{0}', + (github.base_ref == 'develop' || github.ref_name == 'develop') + && '🚀 Develop 브랜치 CI 알림' + || '🎉 새 작업 CI 알림' + ) + }}", + "description": "${{ + format('{0}', + github.event_name == 'pull_request' + && (github.base_ref == 'develop' + && format('Develop 브랜치로 새로운 PR이 등록되었습니다! ({0} → develop)', github.head_ref) + || format('새로운 PR이 등록되었습니다! ({0} → {1})', github.head_ref, github.base_ref) + ) + || 'Develop 브랜치에 Push가 완료되었습니다!' + ) + }}", "url": "${{ github.event.pull_request.html_url || github.event.head_commit.url }}", "color": 5814783, "fields": [ { "name": "Repository", "value": "${{ github.repository }}" + }, + { + "name": "Branch", + "value": "${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}" } ] } diff --git a/package-lock.json b/package-lock.json index 5e866d87..d9563012 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "next": "15.0.3", "react": "^18.3.1", "react-dom": "^18.3.1", + "tailwind-merge": "^2.5.5", "zustand": "^5.0.1" }, "devDependencies": { @@ -17442,6 +17443,15 @@ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "license": "MIT" }, + "node_modules/tailwind-merge": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.4.15", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", diff --git a/package.json b/package.json index a2a3c253..9ff8b551 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "next": "15.0.3", "react": "^18.3.1", "react-dom": "^18.3.1", + "tailwind-merge": "^2.5.5", "zustand": "^5.0.1" }, "devDependencies": { diff --git a/public/icons/IcFiltering.tsx b/public/icons/IcFiltering.tsx new file mode 100644 index 00000000..790cc3c4 --- /dev/null +++ b/public/icons/IcFiltering.tsx @@ -0,0 +1,33 @@ +import { SVGProps } from 'react'; + +interface IcFilteringProps extends SVGProps { + width?: number; + height?: number; + isActive?: boolean; + color?: string; +} + +function IcFiltering({ + width = 24, + height = 24, + isActive = false, + color = '#111827', +}: IcFilteringProps) { + return ( + + + + ); +} + +export default IcFiltering; diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx index c6f4d4b9..ba3b7626 100644 --- a/public/icons/IcSorting.tsx +++ b/public/icons/IcSorting.tsx @@ -4,30 +4,34 @@ interface IcSortingProps extends SVGProps { width?: number; height?: number; isActive?: boolean; + color?: string; } -const TEXT_COLOR = { - default: '#111827', - active: '#F9FAFB', -}; - function IcSorting({ - width = 20, - height = 14, + width = 24, + height = 24, isActive = false, + color = '#111827', }: IcSortingProps) { return ( + ); diff --git a/public/icons/RatingIcon.tsx b/public/icons/RatingIcon.tsx new file mode 100644 index 00000000..4582487b --- /dev/null +++ b/public/icons/RatingIcon.tsx @@ -0,0 +1,32 @@ +import { SVGProps } from 'react'; + +interface RatingIconProps extends SVGProps { + width?: number; + height?: number; + checked: boolean; +} + +function RatingIcon({ + width = 24, + height = 24, + checked = false, + ...props +}: RatingIconProps) { + const heartColor = checked ? '#EA580C' : '#D1D5DB'; + return ( + + + + ); +} +export default RatingIcon; diff --git a/public/icons/index.ts b/public/icons/index.ts index 4faa7804..26a5c656 100644 --- a/public/icons/index.ts +++ b/public/icons/index.ts @@ -1 +1,2 @@ export { default as IcCheck } from './IcCheck'; +export { default as RatingIcon } from './RatingIcon'; diff --git a/public/images/profile.png b/public/images/profile.png new file mode 100644 index 0000000000000000000000000000000000000000..d55453561112a933c52033a274edc071f3286b90 GIT binary patch literal 7392 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 SbWH&O0000 - + ); +} diff --git a/src/components/button2/Button2.stories.ts b/src/components/button2/Button2.stories.ts deleted file mode 100644 index 50061e2a..00000000 --- a/src/components/button2/Button2.stories.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import Button2 from './Button2'; - -const meta: Meta = { - title: 'Components/Button', - component: Button2, - parameters: { - layout: 'centered', - }, -}; - -export default meta; -type Story = StoryObj; - -export const Primary2: Story = { - args: { - // 버튼 props - }, -}; - -// 버튼 컴포넌트 스토리 추가 diff --git a/src/components/button2/Button2.tsx b/src/components/button2/Button2.tsx deleted file mode 100644 index d02aaa5d..00000000 --- a/src/components/button2/Button2.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -const Button2 = () => { - return
hi
; -}; - -export default Button2; diff --git a/src/components/drop-down/DropDown.test.tsx b/src/components/drop-down/DropDown.test.tsx index e69de29b..94ffc879 100644 --- a/src/components/drop-down/DropDown.test.tsx +++ b/src/components/drop-down/DropDown.test.tsx @@ -0,0 +1,10 @@ +import '@testing-library/jest-dom'; +import DropDown from './DropDown'; +import { render, screen } from '@testing-library/react'; + +describe('DropDown', () => { + it('variant:sorting 일 때 렌더링 확인', () => { + render(); + expect(screen.getByRole('button')); + }); +}); diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx index 43c82807..59486d88 100644 --- a/src/components/drop-down/DropDown.tsx +++ b/src/components/drop-down/DropDown.tsx @@ -1,31 +1,104 @@ +import { useState } from 'react'; +import IcSorting from '../../../public/icons/IcSorting'; +import IcFiltering from '../../../public/icons/IcFiltering'; +import Image from 'next/image'; + interface DropDownProps { - variant: 'navbar' | 'find' | 'profile' | 'review'; - size: 'navbar' | 'large' | 'small'; + variant: 'navbar' | 'filtering' | 'sorting'; + items: Array; + size?: 'large' | 'small'; + color?: 'orange-100' | 'gray-50' | 'gray-100' | 'gray-900'; + label?: string; + imgSrc?: string; } -const VARIANTS = { - navbar: ['마이페이지', '로그아웃'], - find: ['마감임박 순', '가까운 모임 날짜 순'], - profile: ['최신순', '오래된 순'], - review: ['평점 높은 순', '평점 낮은 순'], -}; +const JUSTIFIY_ITEMS = { + navbar: `justify-items-end`, + filtering: `justify-items-start`, + sorting: `justify-items-end`, +} as const; + +const SIZES = { + small: ` h-[36px] px-[6px] py-[6px] justify-center`, + large: `h-[40px] px-[12px] py-[8px] justify-start`, +} as const; + +const LABEL_MARGIN = { + filtering: `mr-[4px]`, + sorting: `ml-[4px]`, +} as const; -const SIZE = { - navbar: `w-[40px] h-[40px]`, - small: `w-[36px] h-[36px]`, - large: `w-[110px] h-[40px]`, -}; +const COLORS = { + 'orange-100': { + background: `bg-orange-100`, + text: `text-orange-100`, + border: `border-orange-100`, + }, + 'gray-50': { + background: `bg-gray-50`, + text: `text-gray-50`, + border: `border-gray-50`, + }, + 'gray-100': { + background: `bg-gray-100`, + text: `text-gray-100`, + border: `border-gray-100`, + }, + 'gray-900': { + background: 'bg-gray-900', + text: `text-gray-900`, + border: `border-gray-900`, + }, +} as const; -function DropDown({ variant, size }: DropDownProps) { - const itemList = VARIANTS[variant]; +function DropDown({ + variant, + items, + size, + color = 'gray-900', + label, + imgSrc, +}: DropDownProps) { + const [isActive, setIsActive] = useState(true); return ( -
-
    - - {itemList.map((item, index) => ( -
  • - {item} +
    + {variant === 'navbar' ? ( + + ) : ( + + )} +
      + {items.map((item, index) => ( +
    • +
      + {item} +
    • ))}
    diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx index 4c8bee2c..bd0fec10 100644 --- a/src/components/drop-down/DroptDown.stories.tsx +++ b/src/components/drop-down/DroptDown.stories.tsx @@ -17,16 +17,18 @@ type Story = StoryObj; export const NavBarLarge: Story = { argTypes: { variant: { - options: ['navbar', 'find', 'profile', 'review'], - control: { type: 'select' }, + options: ['navbar', 'filtering', 'sorting'], + control: { type: 'radio' }, }, size: { - options: ['navbar', 'small', 'large'], + options: ['small', 'large'], + control: { type: 'radio' }, }, }, args: { - variant: 'find', + variant: 'filtering', + items: ['3명 이하', '7명 이하', '10명 이하', '10명 이상'], size: 'large', }, }; diff --git a/src/components/rating-display/RatingDisplay.stories.tsx b/src/components/rating-display/RatingDisplay.stories.tsx new file mode 100644 index 00000000..839e53f3 --- /dev/null +++ b/src/components/rating-display/RatingDisplay.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import RatingDisplay from './RatingDisplay'; + +const meta = { + title: 'Components/RatingDisplay', + component: RatingDisplay, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const FourStarRating: Story = { + args: { + ratingCount: 4, + }, +}; diff --git a/src/components/rating-display/RatingDisplay.tsx b/src/components/rating-display/RatingDisplay.tsx new file mode 100644 index 00000000..4c17483b --- /dev/null +++ b/src/components/rating-display/RatingDisplay.tsx @@ -0,0 +1,23 @@ +import RatingIcon from '../../../public/icons/RatingIcon'; + +export default function RatingDisplay({ + ratingCount, +}: { + ratingCount: number; +}) { + const normalizedRating = Math.min(ratingCount, 5); + + return ( +
    + {Array.from({ length: normalizedRating }).map((_, index) => ( +
    + ); +} diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx deleted file mode 100644 index b25cfb66..00000000 --- a/src/components/sorting-button/SortingButton.stories.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import SortingButton from './SortingButton'; - -const meta = { - title: 'Components/SortingButton', - component: SortingButton, - parameters: { - componentSubtitle: '목록의 아이템들의 순서를 정렬하게 만드는 컴포넌트', - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const LargeDefault: Story = { - args: { - label: '마감 임박', - isActive: false, - isLarge: true, - }, -}; -export const LargeActive: Story = { - args: { - label: '마감 임박', - isActive: true, - isLarge: true, - }, -}; - -export const SmallDefault: Story = { - args: { - label: '마감 임박', - isActive: false, - isLarge: false, - }, -}; - -export const SmallActive: Story = { - args: { - label: '마감 임박', - isActive: true, - isLarge: false, - }, -}; diff --git a/src/components/sorting-button/SortingButton.test.tsx b/src/components/sorting-button/SortingButton.test.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx deleted file mode 100644 index 6067931d..00000000 --- a/src/components/sorting-button/SortingButton.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import IcSorting from '../../../public/icons/IcSorting'; - -interface SortingButtonProps { - label?: string; - isActive: boolean; - isLarge: boolean; -} -const COLOR = { - default: 'bg-gray-50 text-gray-900', - active: 'bg-gray-900 text-gray-50', -}; -function SortingButton({ label, isActive, isLarge }: SortingButtonProps) { - return ( - - ); -} - -export default SortingButton; diff --git a/src/components/written-review/WrittenReview.stories.tsx b/src/components/written-review/WrittenReview.stories.tsx new file mode 100644 index 00000000..3fa22bfb --- /dev/null +++ b/src/components/written-review/WrittenReview.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import WrittenReview from './WrittenReview'; + +const meta = { + title: 'Components/WrittenReview', + component: WrittenReview, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const CreatedReview: Story = { + args: { + ratingCount: 4, + comment: + '따듯하게 느껴지는 공간이에요 :) 평소에 달램 이용해보고 싶었는데 이렇게 같이 달램 생기니까 너무 좋아요! 프로그램이 더 많이 늘어났으면 좋겠어요.', + profileImage: + 'https://cdn.pixabay.com/photo/2024/02/17/00/18/cat-8578562_1280.jpg', + userName: '럽윈즈올', + createdAt: '2024.01.25', + }, +}; diff --git a/src/components/written-review/WrittenReview.test.tsx b/src/components/written-review/WrittenReview.test.tsx new file mode 100644 index 00000000..35a40d3e --- /dev/null +++ b/src/components/written-review/WrittenReview.test.tsx @@ -0,0 +1,55 @@ +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import WrittenReview from './WrittenReview'; +import { act } from 'react'; + +describe('WrittenReview Component', () => { + const defaultProfileImage = + 'https://cdn.pixabay.com/photo/2018/02/12/10/45/heart-3147976_1280.jpg'; + const validProfileImage = + 'https://cdn.pixabay.com/photo/2024/02/17/00/18/cat-8578562_1280.jpg'; + const brokenProfileImage = 'https://broken-url.com/image.jpg'; + + it('유효한 이미지 경우 정상적으로 렌더링', () => { + render( + , + ); + const imgElement = screen.getByAltText("Test User's profile picture"); + + expect(imgElement.getAttribute('src')).toContain( + encodeURIComponent(validProfileImage), + ); + }); + + it('유효하지 않은 이미지 경우 기본 이미지로 대체', async () => { + render( + , + ); + + const imgElement = screen.getByAltText("Test User's profile picture"); + + expect(imgElement.getAttribute('src')).toContain( + encodeURIComponent(brokenProfileImage), + ); + + await act(async () => { + imgElement.dispatchEvent(new Event('error')); + }); + + expect(imgElement.getAttribute('src')).toContain( + encodeURIComponent(defaultProfileImage), + ); + }); +}); diff --git a/src/components/written-review/WrittenReview.tsx b/src/components/written-review/WrittenReview.tsx new file mode 100644 index 00000000..df4d53ec --- /dev/null +++ b/src/components/written-review/WrittenReview.tsx @@ -0,0 +1,59 @@ +'use client'; + +import Image from 'next/image'; +import RatingDisplay from '../rating-display/RatingDisplay'; +import { useState, useEffect } from 'react'; + +// 디자인 확정시, 기본 이미지 변경 +const defaultProfileImage = + 'https://cdn.pixabay.com/photo/2018/02/12/10/45/heart-3147976_1280.jpg'; + +interface WrittenReviewProps { + ratingCount: number; + comment: string; + profileImage?: string; + userName: string; + createdAt: string; +} + +export default function WrittenReview({ + ratingCount, + comment, + profileImage, + userName, + createdAt, +}: WrittenReviewProps) { + const [imgSrc, setImgSrc] = useState(profileImage || defaultProfileImage); + + useEffect(() => { + setImgSrc(profileImage || defaultProfileImage); + }, [profileImage]); + + const handleImageError = () => { + setImgSrc(defaultProfileImage); + }; + + return ( +
    + +

    + {comment} +

    +
    + {`${userName}'s +

    + {userName} +

    +

    {createdAt}

    +
    +
    +
    + ); +} diff --git a/tailwind.config.ts b/tailwind.config.ts index 79a60d2b..325a942c 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,12 +1,7 @@ import type { Config } from 'tailwindcss'; export default { - content: [ - './src/pages/**/*.{js,ts,jsx,tsx,mdx}', - './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './src/app/**/*.{js,ts,jsx,tsx,mdx}', - './src/*/.{html,js}', - ], + content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'], theme: { extend: { colors: { From a4bde0937852074be07dcab87f1229d3e9104818 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Fri, 6 Dec 2024 15:52:40 +0900 Subject: [PATCH 04/16] =?UTF-8?q?=E2=99=BB=EF=B8=8F[Refactor]=20dropdown?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81.=20dropdown=EA=B3=BC=20?= =?UTF-8?q?sorting=20=EB=B2=84=ED=8A=BC=20=EB=B6=84=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcDropDown.tsx | 35 ++++++ public/icons/index.ts | 3 + src/components/drop-down/DropDown.tsx | 106 +++++++++++------- .../drop-down/DroptDown.stories.tsx | 16 ++- 4 files changed, 108 insertions(+), 52 deletions(-) create mode 100644 public/icons/IcDropDown.tsx diff --git a/public/icons/IcDropDown.tsx b/public/icons/IcDropDown.tsx new file mode 100644 index 00000000..e480abb7 --- /dev/null +++ b/public/icons/IcDropDown.tsx @@ -0,0 +1,35 @@ +import { SVGProps } from 'react'; + +interface IcDropDownProps extends SVGProps { + width?: number; + height?: number; + isActive?: boolean; + color?: string; +} + +function IcDropDown({ + width = 24, + height = 24, + isActive = false, + color, +}: IcDropDownProps) { + return ( + + + + ); +} + +export default IcDropDown; diff --git a/public/icons/index.ts b/public/icons/index.ts index 26a5c656..98ab6bdd 100644 --- a/public/icons/index.ts +++ b/public/icons/index.ts @@ -1,2 +1,5 @@ export { default as IcCheck } from './IcCheck'; export { default as RatingIcon } from './RatingIcon'; +export { default as IcDropDown } from './IcDropDown'; +export { default as IcSorting } from './IcSorting'; +export { default as IcFiltering } from './IcFiltering'; diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx index 59486d88..fbfc5b7d 100644 --- a/src/components/drop-down/DropDown.tsx +++ b/src/components/drop-down/DropDown.tsx @@ -1,31 +1,23 @@ import { useState } from 'react'; -import IcSorting from '../../../public/icons/IcSorting'; -import IcFiltering from '../../../public/icons/IcFiltering'; +import { IcDropDown } from '../../../public/icons'; import Image from 'next/image'; interface DropDownProps { - variant: 'navbar' | 'filtering' | 'sorting'; - items: Array; - size?: 'large' | 'small'; + variant: 'navbar' | 'filtering'; + items: Array; color?: 'orange-100' | 'gray-50' | 'gray-100' | 'gray-900'; label?: string; imgSrc?: string; } +interface DropDownItem { + value: number; + label: string; +} + const JUSTIFIY_ITEMS = { navbar: `justify-items-end`, filtering: `justify-items-start`, - sorting: `justify-items-end`, -} as const; - -const SIZES = { - small: ` h-[36px] px-[6px] py-[6px] justify-center`, - large: `h-[40px] px-[12px] py-[8px] justify-start`, -} as const; - -const LABEL_MARGIN = { - filtering: `mr-[4px]`, - sorting: `ml-[4px]`, } as const; const COLORS = { @@ -54,50 +46,78 @@ const COLORS = { function DropDown({ variant, items, - size, color = 'gray-900', label, imgSrc, }: DropDownProps) { - const [isActive, setIsActive] = useState(true); + const [isOpen, setIsOpen] = useState(false); + const [isActive, setIsActive] = useState(false); - return ( -
    - {variant === 'navbar' ? ( - - ) : ( - - )} -
      - {items.map((item, index) => ( + ); + case 'filtering': + return ( + <> + {label} + + + ); + } + }; + + return ( +
      + + +
        + {items.map((item) => (
      • - {item} + {item.label}
      • ))} diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx index bd0fec10..29be57ab 100644 --- a/src/components/drop-down/DroptDown.stories.tsx +++ b/src/components/drop-down/DroptDown.stories.tsx @@ -1,6 +1,5 @@ import { Meta, StoryObj } from '@storybook/react'; import DropDown from './DropDown'; -import { Radio } from '@headlessui/react'; const meta = { title: 'Components/DropDown', @@ -17,18 +16,17 @@ type Story = StoryObj; export const NavBarLarge: Story = { argTypes: { variant: { - options: ['navbar', 'filtering', 'sorting'], - control: { type: 'radio' }, - }, - size: { - options: ['small', 'large'], - + options: ['navbar', 'filtering'], control: { type: 'radio' }, }, }, args: { variant: 'filtering', - items: ['3명 이하', '7명 이하', '10명 이하', '10명 이상'], - size: 'large', + items: [ + { value: 1, label: '2~4명' }, + { value: 2, label: '5~7명' }, + { value: 3, label: '8~10명' }, + { value: 4, label: '11명 이상' }, + ], }, }; From 81434df02b6255c9f42e86f4ad5d3bcb6b33d396 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Mon, 2 Dec 2024 17:31:02 +0900 Subject: [PATCH 05/16] =?UTF-8?q?=E2=9C=A8[Feat]=20=EB=93=9C=EB=A1=AD?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EC=83=9D=EC=84=B1=20#47?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcSorting.tsx | 36 +++++++++++++++ src/components/drop-down/DropDown.test.tsx | 0 src/components/drop-down/DropDown.tsx | 0 .../drop-down/DroptDown.stories.tsx | 0 .../sorting-button/SortingButton.stories.tsx | 44 +++++++++++++++++++ .../sorting-button/SortingButton.test.tsx | 0 .../sorting-button/SortingButton.tsx | 25 +++++++++++ 7 files changed, 105 insertions(+) create mode 100644 public/icons/IcSorting.tsx create mode 100644 src/components/drop-down/DropDown.test.tsx create mode 100644 src/components/drop-down/DropDown.tsx create mode 100644 src/components/drop-down/DroptDown.stories.tsx create mode 100644 src/components/sorting-button/SortingButton.stories.tsx create mode 100644 src/components/sorting-button/SortingButton.test.tsx create mode 100644 src/components/sorting-button/SortingButton.tsx diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx new file mode 100644 index 00000000..c6f4d4b9 --- /dev/null +++ b/public/icons/IcSorting.tsx @@ -0,0 +1,36 @@ +import { SVGProps } from 'react'; + +interface IcSortingProps extends SVGProps { + width?: number; + height?: number; + isActive?: boolean; +} + +const TEXT_COLOR = { + default: '#111827', + active: '#F9FAFB', +}; + +function IcSorting({ + width = 20, + height = 14, + isActive = false, +}: IcSortingProps) { + return ( + + + + ); +} + +export default IcSorting; diff --git a/src/components/drop-down/DropDown.test.tsx b/src/components/drop-down/DropDown.test.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx new file mode 100644 index 00000000..b25cfb66 --- /dev/null +++ b/src/components/sorting-button/SortingButton.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import SortingButton from './SortingButton'; + +const meta = { + title: 'Components/SortingButton', + component: SortingButton, + parameters: { + componentSubtitle: '목록의 아이템들의 순서를 정렬하게 만드는 컴포넌트', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LargeDefault: Story = { + args: { + label: '마감 임박', + isActive: false, + isLarge: true, + }, +}; +export const LargeActive: Story = { + args: { + label: '마감 임박', + isActive: true, + isLarge: true, + }, +}; + +export const SmallDefault: Story = { + args: { + label: '마감 임박', + isActive: false, + isLarge: false, + }, +}; + +export const SmallActive: Story = { + args: { + label: '마감 임박', + isActive: true, + isLarge: false, + }, +}; diff --git a/src/components/sorting-button/SortingButton.test.tsx b/src/components/sorting-button/SortingButton.test.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx new file mode 100644 index 00000000..6067931d --- /dev/null +++ b/src/components/sorting-button/SortingButton.tsx @@ -0,0 +1,25 @@ +import IcSorting from '../../../public/icons/IcSorting'; + +interface SortingButtonProps { + label?: string; + isActive: boolean; + isLarge: boolean; +} +const COLOR = { + default: 'bg-gray-50 text-gray-900', + active: 'bg-gray-900 text-gray-50', +}; +function SortingButton({ label, isActive, isLarge }: SortingButtonProps) { + return ( + + ); +} + +export default SortingButton; From ebbe98b195a8aa00b6ada0d3a265d75546c72f2a Mon Sep 17 00:00:00 2001 From: sun <104830526+sunnwave@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:48:03 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=E2=9C=85[Test]=20=EB=93=9C=EB=A1=AD?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20#48=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 드롭다운 스토리북 테스트코드 merge --- src/components/drop-down/DropDown.tsx | 36 +++++++++++++++++++ .../drop-down/DroptDown.stories.tsx | 32 +++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx index e69de29b..43c82807 100644 --- a/src/components/drop-down/DropDown.tsx +++ b/src/components/drop-down/DropDown.tsx @@ -0,0 +1,36 @@ +interface DropDownProps { + variant: 'navbar' | 'find' | 'profile' | 'review'; + size: 'navbar' | 'large' | 'small'; +} + +const VARIANTS = { + navbar: ['마이페이지', '로그아웃'], + find: ['마감임박 순', '가까운 모임 날짜 순'], + profile: ['최신순', '오래된 순'], + review: ['평점 높은 순', '평점 낮은 순'], +}; + +const SIZE = { + navbar: `w-[40px] h-[40px]`, + small: `w-[36px] h-[36px]`, + large: `w-[110px] h-[40px]`, +}; + +function DropDown({ variant, size }: DropDownProps) { + const itemList = VARIANTS[variant]; + + return ( +
        +
          + + {itemList.map((item, index) => ( +
        • + {item} +
        • + ))} +
        +
        + ); +} + +export default DropDown; diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx index e69de29b..4c8bee2c 100644 --- a/src/components/drop-down/DroptDown.stories.tsx +++ b/src/components/drop-down/DroptDown.stories.tsx @@ -0,0 +1,32 @@ +import { Meta, StoryObj } from '@storybook/react'; +import DropDown from './DropDown'; +import { Radio } from '@headlessui/react'; + +const meta = { + title: 'Components/DropDown', + component: DropDown, + parameters: { + componentSubtitle: + '드롭다운 컴포넌트. 정렬 기준을 보여줄 때, NavBar에서 프로필 이미지를 눌렀을 때 사용됨', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const NavBarLarge: Story = { + argTypes: { + variant: { + options: ['navbar', 'find', 'profile', 'review'], + control: { type: 'select' }, + }, + size: { + options: ['navbar', 'small', 'large'], + control: { type: 'radio' }, + }, + }, + args: { + variant: 'find', + size: 'large', + }, +}; From cc4842701e718673a900e59c984e34dbe977f037 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Sun, 8 Dec 2024 16:57:28 +0900 Subject: [PATCH 07/16] =?UTF-8?q?=E2=99=BB=EF=B8=8F[Refactor]=20storybook?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81-=20navbar,=20filtering=20small,=20f?= =?UTF-8?q?iltering=20large=EB=A1=9C=20=EB=B6=84=EB=A5=98=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=ED=99=95=EC=9D=B8=20=EA=B0=80=EB=8A=A5=20#84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../drop-down/DroptDown.stories.tsx | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx index 32a7b9a8..59660c0b 100644 --- a/src/components/drop-down/DroptDown.stories.tsx +++ b/src/components/drop-down/DroptDown.stories.tsx @@ -15,13 +15,27 @@ export default meta; type Story = StoryObj; export const NavBarLarge: Story = { - argTypes: { - variant: { - options: ['navbar', 'filtering'], + args: { + variant: 'navbar', + items: [ + { value: 1, label: '마이페이지' }, + { value: 2, label: '로그아웃' }, + ], + }, +}; - control: { type: 'radio' }, - }, +export const FilteringLarge: Story = { + args: { + variant: 'filtering', + items: [ + { value: 1, label: '온라인' }, + { value: 2, label: '오프라인' }, + ], + label: '온/오프라인', }, +}; + +export const FilteringSmall: Story = { args: { variant: 'filtering', items: [ @@ -30,5 +44,6 @@ export const NavBarLarge: Story = { { value: 3, label: '8~10명' }, { value: 4, label: '11명 이상' }, ], + label: '인원수', }, }; From e342212b98c213a92716043c4e9b36726bdcb1d4 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Sun, 8 Dec 2024 17:06:51 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=E2=99=BB=EF=B8=8F[Refactor]=20Avatar=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=82=AC=EC=9A=A9=20#84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/drop-down/DropDown.tsx | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/drop-down/DropDown.tsx b/src/components/drop-down/DropDown.tsx index a156644f..278a207e 100644 --- a/src/components/drop-down/DropDown.tsx +++ b/src/components/drop-down/DropDown.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { IcDropDown } from '../../../public/icons'; -import Image from 'next/image'; +import Avatar from '../avatar/Avatar'; interface DropDownProps { variant: 'navbar' | 'filtering'; @@ -14,12 +14,7 @@ interface DropDownItem { value: number; } -function DropDown({ - variant, - items, - label = '온/오프라인', - imgSrc, -}: DropDownProps) { +function DropDown({ variant, items, label, imgSrc }: DropDownProps) { const [isOpen, setIsOpen] = useState(false); const [isActive, setIsActive] = useState(false); @@ -44,11 +39,10 @@ function DropDown({ className="relative h-[40px] w-[40px] justify-center" onClick={handleDropDown} > - {'nav_profile'} ); From e5b465bff22ea7291ea1c5c6e76ff2f669161c9d Mon Sep 17 00:00:00 2001 From: sunnwave Date: Sun, 8 Dec 2024 17:53:58 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=E2=9C=85[Test]=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20#84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/drop-down/DropDown.test.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/drop-down/DropDown.test.tsx b/src/components/drop-down/DropDown.test.tsx index 94ffc879..712235ec 100644 --- a/src/components/drop-down/DropDown.test.tsx +++ b/src/components/drop-down/DropDown.test.tsx @@ -4,7 +4,15 @@ import { render, screen } from '@testing-library/react'; describe('DropDown', () => { it('variant:sorting 일 때 렌더링 확인', () => { - render(); + render( + , + ); expect(screen.getByRole('button')); }); }); From f7747d2b107d414f1955a166a73be7c8a709135a Mon Sep 17 00:00:00 2001 From: sunnwave Date: Sun, 8 Dec 2024 18:01:50 +0900 Subject: [PATCH 10/16] =?UTF-8?q?=F0=9F=94=A5[Remove]=20SortingButton.tes.?= =?UTF-8?q?tsx=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/sorting-button/SortingButton.test.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/components/sorting-button/SortingButton.test.tsx diff --git a/src/components/sorting-button/SortingButton.test.tsx b/src/components/sorting-button/SortingButton.test.tsx deleted file mode 100644 index e69de29b..00000000 From 42fc1b1be833e40af557afe4c646bf251cf8af9b Mon Sep 17 00:00:00 2001 From: sunnwave Date: Sun, 8 Dec 2024 20:03:19 +0900 Subject: [PATCH 11/16] =?UTF-8?q?=F0=9F=92=84[Design]=20SortingButton=20UI?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20=EC=A0=81=EC=9A=A9,=20=E2=9C=85[Test]?= =?UTF-8?q?=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcDropDown.tsx | 1 - public/icons/IcSorting.tsx | 7 ++-- .../sorting-button/SortingButton.stories.tsx | 27 ++---------- .../sorting-button/SortingButton.tsx | 42 +++++++++++++------ 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/public/icons/IcDropDown.tsx b/public/icons/IcDropDown.tsx index 624df788..7865648c 100644 --- a/public/icons/IcDropDown.tsx +++ b/public/icons/IcDropDown.tsx @@ -23,7 +23,6 @@ function IcDropDown({ xmlns="http://www.w3.org/2000/svg" > diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx index b25cfb66..7a52bf29 100644 --- a/src/components/sorting-button/SortingButton.stories.tsx +++ b/src/components/sorting-button/SortingButton.stories.tsx @@ -12,33 +12,14 @@ const meta = { export default meta; type Story = StoryObj; -export const LargeDefault: Story = { +export const byDate: Story = { args: { - label: '마감 임박', - isActive: false, - isLarge: true, - }, -}; -export const LargeActive: Story = { - args: { - label: '마감 임박', - isActive: true, - isLarge: true, - }, -}; - -export const SmallDefault: Story = { - args: { - label: '마감 임박', - isActive: false, - isLarge: false, + variant: 'byDate', }, }; -export const SmallActive: Story = { +export const byDeadline: Story = { args: { - label: '마감 임박', - isActive: true, - isLarge: false, + variant: 'byDeadline', }, }; diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx index 6067931d..221ec14a 100644 --- a/src/components/sorting-button/SortingButton.tsx +++ b/src/components/sorting-button/SortingButton.tsx @@ -1,23 +1,39 @@ -import IcSorting from '../../../public/icons/IcSorting'; +import { useState } from 'react'; +import { IcSorting } from '../../../public/icons/index'; interface SortingButtonProps { - label?: string; - isActive: boolean; - isLarge: boolean; + variant: 'byDeadline' | 'byDate'; } -const COLOR = { - default: 'bg-gray-50 text-gray-900', - active: 'bg-gray-900 text-gray-50', -}; -function SortingButton({ label, isActive, isLarge }: SortingButtonProps) { + +function SortingButton({ variant }: SortingButtonProps) { + const [isActive, setIsActive] = useState(false); + + const onClickSorting = (): void => { + setIsActive(!isActive); + }; + + const getLabel = (variant: string) => { + switch (variant) { + case 'byDeadline': + return '마감임박순'; + + case 'byDate': + return isActive ? '오래된순' : '최신순'; + } + }; return ( ); } From 43ca3b4b2ad9a96b0a9d3af4277840a1a5e4c7f4 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Mon, 9 Dec 2024 13:50:27 +0900 Subject: [PATCH 12/16] =?UTF-8?q?=F0=9F=8E=A8[Style]=20=EC=BB=AC=EB=9F=AC?= =?UTF-8?q?=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EC=A0=81=EC=9A=A9=20#94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcSorting.tsx | 2 +- src/components/sorting-button/SortingButton.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx index d0057520..d1a29f93 100644 --- a/public/icons/IcSorting.tsx +++ b/public/icons/IcSorting.tsx @@ -20,7 +20,7 @@ function IcSorting({ viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" - className={`${isActive ? color : 'stroke-gray-dark-hover'}`} + className={`${isActive ? color : 'stroke-gray-dark-02'}`} > - + {getLabel(variant)} From a9f01475ce981ca398f13c906219284a797f9665 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Tue, 10 Dec 2024 09:02:46 +0900 Subject: [PATCH 13/16] =?UTF-8?q?=E2=9C=A8[Feat]=20sorting=20button=20oncl?= =?UTF-8?q?ick=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20#94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcSorting.tsx | 26 +++++++++++++++++-- .../sorting-button/SortingButton.stories.tsx | 2 ++ .../sorting-button/SortingButton.tsx | 24 ++++++++++++----- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx index d1a29f93..816faf2f 100644 --- a/public/icons/IcSorting.tsx +++ b/public/icons/IcSorting.tsx @@ -25,16 +25,38 @@ function IcSorting({ + + // + // + // + // ); } diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx index 7a52bf29..cbc1cafe 100644 --- a/src/components/sorting-button/SortingButton.stories.tsx +++ b/src/components/sorting-button/SortingButton.stories.tsx @@ -15,11 +15,13 @@ type Story = StoryObj; export const byDate: Story = { args: { variant: 'byDate', + onClickSorting: (e) => alert(e), }, }; export const byDeadline: Story = { args: { variant: 'byDeadline', + onClickSorting: (e) => alert(e), }, }; diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx index acd8c95e..e83b6b53 100644 --- a/src/components/sorting-button/SortingButton.tsx +++ b/src/components/sorting-button/SortingButton.tsx @@ -3,16 +3,28 @@ import { IcSorting } from '../../../public/icons/index'; interface SortingButtonProps { variant: 'byDeadline' | 'byDate'; + onClickSorting: (sortBy: string) => void; } -function SortingButton({ variant }: SortingButtonProps) { +function SortingButton({ variant, onClickSorting }: SortingButtonProps) { const [isActive, setIsActive] = useState(false); - const onClickSorting = (): void => { + const onClick = (): void => { + let param; + switch (variant) { + case 'byDeadline': + param = isActive ? 'NEWEST' : 'DEADLINE'; + break; + + case 'byDate': + param = isActive ? 'NEWEST' : 'OLDEST'; + break; + } + onClickSorting(param); setIsActive(!isActive); }; - const getLabel = (variant: string) => { + const renderLabel = (variant: string) => { switch (variant) { case 'byDeadline': return '마감임박순'; @@ -23,17 +35,17 @@ function SortingButton({ variant }: SortingButtonProps) { }; return ( ); } From 3e853ff65d1fcb065b18524d387602f67c3bf422 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Tue, 10 Dec 2024 11:43:30 +0900 Subject: [PATCH 14/16] =?UTF-8?q?=E2=9C=85[Test]=20SortingButton=20jest=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/IcSorting.tsx | 22 ---------- .../sorting-button/SortingButton.test.tsx | 43 +++++++++++++++++++ .../sorting-button/SortingButton.tsx | 7 +-- 3 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 src/components/sorting-button/SortingButton.test.tsx diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx index 816faf2f..c5be40d6 100644 --- a/public/icons/IcSorting.tsx +++ b/public/icons/IcSorting.tsx @@ -35,28 +35,6 @@ function IcSorting({ strokeLinejoin="round" /> - - // - // - // - // ); } diff --git a/src/components/sorting-button/SortingButton.test.tsx b/src/components/sorting-button/SortingButton.test.tsx new file mode 100644 index 00000000..edb21c90 --- /dev/null +++ b/src/components/sorting-button/SortingButton.test.tsx @@ -0,0 +1,43 @@ +import { render, screen } from '@testing-library/react'; +import SortingButton from './SortingButton'; +import userEvent from '@testing-library/user-event'; +import '@testing-library/jest-dom'; + +describe('SortingButton', () => { + const mockOnClickSorting = jest.fn(); + + it('마감임박순 Sorting Button 렌더링 확인', async () => { + render( + , + ); + + const button = screen.getByRole('button'); + expect(button).toBeInTheDocument(); + + //유저가 최초 클릭 시 최신순->마감임박 순으로 전환. 'DEADLINE'으로 onClickSorting 함수 호출 + await userEvent.click(button); + expect(mockOnClickSorting).toHaveBeenCalledWith('DEADLINE'); + //유저가 두번째 클릭 시 마감임박->최신순 순으로 전환. 'NEWEST'으로 onClickSorting 함수 호출 + await userEvent.click(button); + expect(mockOnClickSorting).toHaveBeenCalledWith('NEWEST'); + }); + + it('날짜순 SortingButton 렌더링 확인', async () => { + render( + , + ); + + const button = screen.getByRole('button'); + expect(button).toBeInTheDocument(); + + //유저가 최초 클릭 시 최신순->오래된 순으로 전환. 'OLDEST'으로 onClickSorting 함수 호출 + await userEvent.click(button); + expect(mockOnClickSorting).toHaveBeenCalledWith('OLDEST'); + //유저가 두번째 클릭 시 오래된 순->최신순 순으로 전환. 'NEWEST'으로 onClickSorting 함수 호출 + await userEvent.click(button); + expect(mockOnClickSorting).toHaveBeenCalledWith('NEWEST'); + }); +}); diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx index e83b6b53..1c46c070 100644 --- a/src/components/sorting-button/SortingButton.tsx +++ b/src/components/sorting-button/SortingButton.tsx @@ -11,6 +11,7 @@ function SortingButton({ variant, onClickSorting }: SortingButtonProps) { const onClick = (): void => { let param; + setIsActive(!isActive); switch (variant) { case 'byDeadline': param = isActive ? 'NEWEST' : 'DEADLINE'; @@ -21,10 +22,9 @@ function SortingButton({ variant, onClickSorting }: SortingButtonProps) { break; } onClickSorting(param); - setIsActive(!isActive); }; - const renderLabel = (variant: string) => { + const renderLabel = () => { switch (variant) { case 'byDeadline': return '마감임박순'; @@ -33,6 +33,7 @@ function SortingButton({ variant, onClickSorting }: SortingButtonProps) { return isActive ? '오래된순' : '최신순'; } }; + return ( ); } From e27c53789d1f588fb43de1bfe2426d5a8c9ade7f Mon Sep 17 00:00:00 2001 From: sunnwave Date: Tue, 10 Dec 2024 16:18:18 +0900 Subject: [PATCH 15/16] =?UTF-8?q?=F0=9F=94=A5[Remove]DroptDown.stories.tsx?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C(=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=EB=A1=9C=20=EC=9D=B8=ED=95=B4=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=ED=96=88=EC=9C=BC=EB=82=98=20merge=20=EA=B3=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A4=91=20=EC=82=AD=EC=A0=9C=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EC=9D=8C)=20#94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../drop-down/DroptDown.stories.tsx | 49 ------------------- 1 file changed, 49 deletions(-) delete mode 100644 src/components/drop-down/DroptDown.stories.tsx diff --git a/src/components/drop-down/DroptDown.stories.tsx b/src/components/drop-down/DroptDown.stories.tsx deleted file mode 100644 index 59660c0b..00000000 --- a/src/components/drop-down/DroptDown.stories.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; -import DropDown from './DropDown'; - -const meta = { - title: 'Components/DropDown', - component: DropDown, - parameters: { - layout: 'centered', - componentSubtitle: - '드롭다운 컴포넌트. 정렬 기준을 보여줄 때, NavBar에서 프로필 이미지를 눌렀을 때 사용됨', - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const NavBarLarge: Story = { - args: { - variant: 'navbar', - items: [ - { value: 1, label: '마이페이지' }, - { value: 2, label: '로그아웃' }, - ], - }, -}; - -export const FilteringLarge: Story = { - args: { - variant: 'filtering', - items: [ - { value: 1, label: '온라인' }, - { value: 2, label: '오프라인' }, - ], - label: '온/오프라인', - }, -}; - -export const FilteringSmall: Story = { - args: { - variant: 'filtering', - items: [ - { value: 1, label: '2~4명' }, - { value: 2, label: '5~7명' }, - { value: 3, label: '8~10명' }, - { value: 4, label: '11명 이상' }, - ], - label: '인원수', - }, -}; From 2667ebd7682e2f8bf015f74387c4bbad5368f815 Mon Sep 17 00:00:00 2001 From: sunnwave Date: Wed, 11 Dec 2024 13:49:17 +0900 Subject: [PATCH 16/16] =?UTF-8?q?=F0=9F=90=9B[Fix]=20=EC=B5=9C=EC=8B=A0?= =?UTF-8?q?=EC=88=9C,=20=EC=98=A4=EB=9E=98=EB=90=9C=EC=88=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20=EB=B2=84=ED=8A=BC=EC=9D=BC=20=EB=95=8C=EB=8A=94=20?= =?UTF-8?q?=EC=9D=BC=EA=B4=84=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=20=EC=BB=AC=EB=9F=AC=EB=A1=9C=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20#94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/sorting-button/SortingButton.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx index 1c46c070..68ffb7ad 100644 --- a/src/components/sorting-button/SortingButton.tsx +++ b/src/components/sorting-button/SortingButton.tsx @@ -10,18 +10,18 @@ function SortingButton({ variant, onClickSorting }: SortingButtonProps) { const [isActive, setIsActive] = useState(false); const onClick = (): void => { - let param; + let sortBy; setIsActive(!isActive); switch (variant) { case 'byDeadline': - param = isActive ? 'NEWEST' : 'DEADLINE'; + sortBy = isActive ? 'NEWEST' : 'DEADLINE'; break; case 'byDate': - param = isActive ? 'NEWEST' : 'OLDEST'; + sortBy = isActive ? 'NEWEST' : 'OLDEST'; break; } - onClickSorting(param); + onClickSorting(sortBy); }; const renderLabel = () => { @@ -37,14 +37,17 @@ function SortingButton({ variant, onClickSorting }: SortingButtonProps) { return (