diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx index ba3b7626..c5be40d6 100644 --- a/public/icons/IcSorting.tsx +++ b/public/icons/IcSorting.tsx @@ -11,7 +11,7 @@ function IcSorting({ width = 24, height = 24, isActive = false, - color = '#111827', + color, }: IcSortingProps) { return ( ); diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx new file mode 100644 index 00000000..cbc1cafe --- /dev/null +++ b/src/components/sorting-button/SortingButton.stories.tsx @@ -0,0 +1,27 @@ +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 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.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 new file mode 100644 index 00000000..68ffb7ad --- /dev/null +++ b/src/components/sorting-button/SortingButton.tsx @@ -0,0 +1,57 @@ +import { useState } from 'react'; +import { IcSorting } from '../../../public/icons/index'; + +interface SortingButtonProps { + variant: 'byDeadline' | 'byDate'; + onClickSorting: (sortBy: string) => void; +} + +function SortingButton({ variant, onClickSorting }: SortingButtonProps) { + const [isActive, setIsActive] = useState(false); + + const onClick = (): void => { + let sortBy; + setIsActive(!isActive); + switch (variant) { + case 'byDeadline': + sortBy = isActive ? 'NEWEST' : 'DEADLINE'; + break; + + case 'byDate': + sortBy = isActive ? 'NEWEST' : 'OLDEST'; + break; + } + onClickSorting(sortBy); + }; + + const renderLabel = () => { + switch (variant) { + case 'byDeadline': + return '마감임박순'; + + case 'byDate': + return isActive ? '오래된순' : '최신순'; + } + }; + + return ( + + ); +} + +export default SortingButton;