From 18e3a96df093afde5ebf0a528d3bc9aa4f1d6091 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 00:50:05 +0000 Subject: [PATCH 1/7] Create draft PR for #819 From 6090cde0e75dfa2ad6cd792f1064339a892cb4f2 Mon Sep 17 00:00:00 2001 From: Seongjin Hong Date: Tue, 15 Oct 2024 17:27:11 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=EC=97=AC=EB=9F=AC=20=EC=A7=80?= =?UTF-8?q?=EC=9B=90=EC=9E=90=20=EC=84=A0=ED=83=9D=20=ED=86=A0=EA=B8=80=20?= =?UTF-8?q?UI=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/MultiSelectToggle/index.tsx | 22 +++++++++++++++++++ .../dashboard/MultiSelectToggle/style.ts | 19 ++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 frontend/src/components/dashboard/MultiSelectToggle/index.tsx create mode 100644 frontend/src/components/dashboard/MultiSelectToggle/style.ts diff --git a/frontend/src/components/dashboard/MultiSelectToggle/index.tsx b/frontend/src/components/dashboard/MultiSelectToggle/index.tsx new file mode 100644 index 000000000..948e9d159 --- /dev/null +++ b/frontend/src/components/dashboard/MultiSelectToggle/index.tsx @@ -0,0 +1,22 @@ +import ToggleSwitch from '@components/_common/atoms/ToggleSwitch'; + +import S from './style'; + +interface MultiSelectToggleProps { + isSelectMode: boolean; + onToggle: () => void; +} + +export default function MultiSelectToggle({ isSelectMode, onToggle }: MultiSelectToggleProps) { + return ( + + 여러 지원자 선택 + + + ); +} diff --git a/frontend/src/components/dashboard/MultiSelectToggle/style.ts b/frontend/src/components/dashboard/MultiSelectToggle/style.ts new file mode 100644 index 000000000..2594db8a7 --- /dev/null +++ b/frontend/src/components/dashboard/MultiSelectToggle/style.ts @@ -0,0 +1,19 @@ +import styled from '@emotion/styled'; + +const ToggleWrapper = styled.div` + display: flex; + gap: 1.2rem; + align-items: center; +`; + +const ToggleLabel = styled.span` + ${({ theme }) => theme.typography.heading[200]}; + color: ${({ theme }) => theme.baseColors.grayscale[800]}; +`; + +const S = { + ToggleWrapper, + ToggleLabel, +}; + +export default S; From 31a1db83633e39dc49b995470dcb0d44407015fb Mon Sep 17 00:00:00 2001 From: Seongjin Hong Date: Tue, 15 Oct 2024 17:27:38 +0900 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20ProcessBoard=EC=97=90=20?= =?UTF-8?q?=ED=86=A0=EA=B8=80=20=EC=9A=94=EC=86=8C=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/dashboard/ProcessBoard/index.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/dashboard/ProcessBoard/index.tsx b/frontend/src/components/dashboard/ProcessBoard/index.tsx index b134a527f..a06d0a651 100644 --- a/frontend/src/components/dashboard/ProcessBoard/index.tsx +++ b/frontend/src/components/dashboard/ProcessBoard/index.tsx @@ -1,21 +1,34 @@ import { Process } from '@customTypes/process'; import ApplicantModal from '@components/ApplicantModal'; +import { useMultiApplicant } from '@contexts/MultiApplicantContext'; import ProcessColumn from '../ProcessColumn'; import SideFloatingMessageForm from '../SideFloatingMessageForm'; import S from './style'; +import MultiSelectToggle from '../MultiSelectToggle'; -interface KanbanBoardProps { +interface ProcessBoardProps { processes: Process[]; // eslint-disable-next-line react/no-unused-prop-types isSubTab?: boolean; showRejectedApplicant?: boolean; } -export default function ProcessBoard({ processes, showRejectedApplicant = false }: KanbanBoardProps) { +export default function ProcessBoard({ processes, showRejectedApplicant = false }: ProcessBoardProps) { + const { isMultiType, toggleIsMultiType, resetApplicants } = useMultiApplicant(); + + const handleToggleMultiType = () => { + if (isMultiType) resetApplicants(); + toggleIsMultiType(); + }; + return ( {/* TODO: isSubTab을 가져와서 SubTab을 렌더링 합니다. */} + {processes.map((process, index) => ( Date: Wed, 16 Oct 2024 16:05:17 +0900 Subject: [PATCH 4/7] =?UTF-8?q?test:=20MultiSelectToggle=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EB=B6=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MultiSelectToggle.stories.tsx | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx diff --git a/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx b/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx new file mode 100644 index 000000000..34c378506 --- /dev/null +++ b/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx @@ -0,0 +1,74 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { MultiApplicantContextProvider } from '@contexts/MultiApplicantContext'; +import { DropdownProvider } from '@contexts/DropdownContext'; +import MultiSelectToggle from '.'; + +const meta = { + title: 'Organisms/Dashboard/MultiSelectToggle', + component: MultiSelectToggle, + parameters: { + layout: 'centered', + docs: { + description: { + component: + 'MultiSelectToggle 컴포넌트는 여러 지원자의 선택 여부를 토글하고, 선택시 실행할 공통 작업을 제공하는 컴포넌트입니다.', + }, + }, + }, + argTypes: { + isToggled: { control: 'boolean', description: '여러 지원자 선택 토글 여부를 나타냅니다.' }, + selectedApplicantIds: { + description: '선택된 지원자들의 ID값 목록을 나타냅니다.', + }, + }, + tags: ['autodocs'], + decorators: [ + (Child) => ( +
+ + + + + +
+ ), + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const processes = [ + { + processName: '지원서', + processId: 1, + }, + { + processName: '프로세스 1', + processId: 4, + }, + { + processName: '프로세스 2', + processId: 2, + }, + { + processName: '프로세스 3', + processId: 5, + }, + { + processName: '최종 합격', + processId: 6, + }, +]; + +const selectedApplicantIds = [1, 2, 3]; + +export const MultiSelectToggleDefault: Story = { + args: { + isToggled: false, + processes, + selectedApplicantIds, + }, +}; From 45cdfb88a6c267f45d8f3782176cddfff9507c53 Mon Sep 17 00:00:00 2001 From: Seongjin Hong Date: Thu, 17 Oct 2024 10:49:51 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=ED=86=A0=EA=B8=80=EC=8B=9C=20?= =?UTF-8?q?=EB=93=9C=EB=A1=AD=EB=8B=A4=EC=9A=B4=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EC=95=A0=EB=8B=88=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20UI=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MultiSelectToggle.stories.tsx | 9 +- .../dashboard/MultiSelectToggle/index.tsx | 113 ++++++++++++++++-- .../dashboard/MultiSelectToggle/style.ts | 25 +++- 3 files changed, 133 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx b/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx index 34c378506..84ae625a6 100644 --- a/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx +++ b/frontend/src/components/dashboard/MultiSelectToggle/MultiSelectToggle.stories.tsx @@ -25,7 +25,14 @@ const meta = { decorators: [ (Child) => (
diff --git a/frontend/src/components/dashboard/MultiSelectToggle/index.tsx b/frontend/src/components/dashboard/MultiSelectToggle/index.tsx index 948e9d159..6cacb7550 100644 --- a/frontend/src/components/dashboard/MultiSelectToggle/index.tsx +++ b/frontend/src/components/dashboard/MultiSelectToggle/index.tsx @@ -1,22 +1,111 @@ +import { useEffect, useState } from 'react'; + +import { useMultiApplicant } from '@contexts/MultiApplicantContext'; +import { DropdownProvider } from '@contexts/DropdownContext'; +import type { SimpleProcess } from '@hooks/useProcess'; + +import useApplicant from '@hooks/useApplicant'; import ToggleSwitch from '@components/_common/atoms/ToggleSwitch'; +import Dropdown from '@components/_common/molecules/Dropdown'; +import DropdownItemRenderer, { DropdownItemType } from '@components/_common/molecules/DropdownItemRenderer'; import S from './style'; interface MultiSelectToggleProps { - isSelectMode: boolean; - onToggle: () => void; + isToggled: boolean; + processes: SimpleProcess[]; + selectedApplicantIds: number[]; } -export default function MultiSelectToggle({ isSelectMode, onToggle }: MultiSelectToggleProps) { +export default function MultiSelectToggle({ isToggled, processes, selectedApplicantIds }: MultiSelectToggleProps) { + const { toggleIsMultiType, resetApplicants } = useMultiApplicant(); + const { mutate: moveApplicantProcess } = useApplicant({}); + + const [isDropdownVisible, setIsDropdownVisible] = useState(false); + const [isToggleVisible, setIsToggleVisible] = useState(true); + + useEffect(() => { + if (isToggled) { + setIsToggleVisible(false); + const timer = setTimeout(() => setIsDropdownVisible(true), 200); + return () => clearTimeout(timer); + } + + setIsDropdownVisible(false); + const timer = setTimeout(() => setIsToggleVisible(true), 300); + return () => clearTimeout(timer); + }, [isToggled]); + + const handleToggleMultiType = () => { + if (isToggled) resetApplicants(); + toggleIsMultiType(); + }; + + const menuItems: DropdownItemType[] = [ + { + type: 'subTrigger', + id: 'moveProcess', + name: '단계 이동', + items: processes.map(({ processName, processId }) => ({ + type: 'clickable', + id: processId, + name: processName, + onClick: ({ targetProcessId }) => { + moveApplicantProcess({ processId: targetProcessId, applicants: selectedApplicantIds }); + }, + })), + }, + { + type: 'clickable', + id: 'emailButton', + name: '이메일 보내기', + hasSeparate: true, + onClick: () => { + // TODO: 복수 지원자에 대한 이메일 전송 구현이 필요합니다. (24/10/16 아르) + console.log(`${selectedApplicantIds.join(', ')} 지원자들에게 이메일을 보냅니다.`); + }, + }, + { + type: 'clickable', + id: 'rejectButton', + name: '불합격 처리', + isHighlight: true, + hasSeparate: true, + onClick: () => { + // TODO: 일괄 불합격/불합격 해제에 해당하는 API 연결 Mutation 구현이 필요합니다. (24/10/16 아르) + console.log(`${selectedApplicantIds.join(', ')} 지원자들을 모두 불합격 처리합니다.`); + }, + }, + ]; + return ( - - 여러 지원자 선택 - - + + + 여러 지원자 선택 + + + + + + + + + + + ); } diff --git a/frontend/src/components/dashboard/MultiSelectToggle/style.ts b/frontend/src/components/dashboard/MultiSelectToggle/style.ts index 2594db8a7..8373ad478 100644 --- a/frontend/src/components/dashboard/MultiSelectToggle/style.ts +++ b/frontend/src/components/dashboard/MultiSelectToggle/style.ts @@ -1,9 +1,17 @@ import styled from '@emotion/styled'; -const ToggleWrapper = styled.div` +const Wrapper = styled.div` + display: flex; + justify-content: flex-end; + position: relative; +`; + +const ToggleWrapper = styled.div<{ isVisible: boolean }>` display: flex; gap: 1.2rem; align-items: center; + transition: transform 0.3s ease-in-out; + transform: ${({ isVisible }) => (isVisible ? 'translateX(0)' : 'translateX(-13.8rem)')}; `; const ToggleLabel = styled.span` @@ -11,9 +19,24 @@ const ToggleLabel = styled.span` color: ${({ theme }) => theme.baseColors.grayscale[800]}; `; +const DropdownWrapper = styled.div<{ isVisible: boolean }>` + position: absolute; + transform: translateX(0); + + opacity: ${({ isVisible }) => (isVisible ? 1 : 0.01)}; + visibility: ${({ isVisible }) => (isVisible ? 'visible' : 'hidden')}; + transition: + opacity 0.3s ease-in-out, + visibility 0.3s ease-in-out; + + color: ${({ theme }) => theme.baseColors.grayscale[800]}; +`; + const S = { + Wrapper, ToggleWrapper, ToggleLabel, + DropdownWrapper, }; export default S; From 6fc640f08546525f6e9b738bc0313c174a4fe924 Mon Sep 17 00:00:00 2001 From: Seongjin Hong Date: Thu, 17 Oct 2024 15:29:28 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20fe/develop=EC=9D=98=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=20=EC=BB=A4=EB=B0=8B=20=EB=82=B4=EC=97=AD=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/dashboard/MultiSelectToggle/index.tsx | 6 +----- .../src/components/dashboard/MultiSelectToggle/style.ts | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/src/components/dashboard/MultiSelectToggle/index.tsx b/frontend/src/components/dashboard/MultiSelectToggle/index.tsx index 6cacb7550..39c3dc2b1 100644 --- a/frontend/src/components/dashboard/MultiSelectToggle/index.tsx +++ b/frontend/src/components/dashboard/MultiSelectToggle/index.tsx @@ -95,14 +95,10 @@ export default function MultiSelectToggle({ isToggled, processes, selectedApplic - + diff --git a/frontend/src/components/dashboard/MultiSelectToggle/style.ts b/frontend/src/components/dashboard/MultiSelectToggle/style.ts index 8373ad478..0a59a534a 100644 --- a/frontend/src/components/dashboard/MultiSelectToggle/style.ts +++ b/frontend/src/components/dashboard/MultiSelectToggle/style.ts @@ -3,7 +3,6 @@ import styled from '@emotion/styled'; const Wrapper = styled.div` display: flex; justify-content: flex-end; - position: relative; `; const ToggleWrapper = styled.div<{ isVisible: boolean }>` From 030f3b75b1b4bb07aacd10d4b58aa74664f536e3 Mon Sep 17 00:00:00 2001 From: Seongjin Hong Date: Thu, 17 Oct 2024 15:37:31 +0900 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=EB=A1=9C=EC=BB=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=96=88=EB=8D=98=20=EC=BD=94=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/dashboard/ProcessBoard/index.tsx | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/dashboard/ProcessBoard/index.tsx b/frontend/src/components/dashboard/ProcessBoard/index.tsx index e5678a831..dfcd9ac7c 100644 --- a/frontend/src/components/dashboard/ProcessBoard/index.tsx +++ b/frontend/src/components/dashboard/ProcessBoard/index.tsx @@ -1,11 +1,9 @@ -import ApplicantModal from '@components/ApplicantModal'; -import { Process } from '@customTypes/process'; +import type { Process } from '@customTypes/process'; -import { useMultiApplicant } from '@contexts/MultiApplicantContext'; +import ApplicantModal from '@components/ApplicantModal'; import ProcessColumn from '../ProcessColumn'; import SideFloatingMessageForm from '../SideFloatingMessageForm'; import S from './style'; -import MultiSelectToggle from '../MultiSelectToggle'; interface ProcessBoardProps { processes: Process[]; @@ -20,20 +18,9 @@ export default function ProcessBoard({ showRejectedApplicant = false, searchedName = '', }: ProcessBoardProps) { - const { isMultiType, toggleIsMultiType, resetApplicants } = useMultiApplicant(); - - const handleToggleMultiType = () => { - if (isMultiType) resetApplicants(); - toggleIsMultiType(); - }; - return ( {/* TODO: isSubTab을 가져와서 SubTab을 렌더링 합니다. */} - {processes.map((process, index) => (