Skip to content

Commit bf5ff79

Browse files
Merge pull request #176 from D3vPals/feat/#171
합/불합 리스트에서 지원자 클릭시 리다이렉트 후 정보 노출
2 parents 42dd49e + c1e3ee0 commit bf5ff79

File tree

14 files changed

+278
-23
lines changed

14 files changed

+278
-23
lines changed

src/components/common/modal/Modal.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { useState } from 'react';
22
import { createPortal } from 'react-dom';
3-
import { XMarkIcon, CheckCircleIcon } from '@heroicons/react/24/outline';
3+
import { CheckCircleIcon } from '@heroicons/react/24/outline';
44
import * as S from './Modal.styled';
55
import ScrollPreventor from './ScrollPreventor';
6+
import ModalCloseButton from './ModalCloseButton';
67
import { useOutsideClick } from '../../../hooks/useOutsideClick';
78

89
interface ModalProps {
@@ -35,9 +36,7 @@ const Modal = ({ children, isOpen, onClose }: ModalProps) => {
3536
onAnimationEnd={handleAnimationEnd}
3637
>
3738
<S.ModalBody ref={modalRefs}>
38-
<S.ModalCloseButton onClick={handleClose}>
39-
<XMarkIcon />
40-
</S.ModalCloseButton>
39+
<ModalCloseButton onClose={handleClose} />
4140
<S.ModalIconWrapper>
4241
<CheckCircleIcon />
4342
</S.ModalIconWrapper>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as S from './Modal.styled';
2+
import { XMarkIcon } from '@heroicons/react/24/outline';
3+
interface ModalCloseButtonProps {
4+
onClose: () => void;
5+
}
6+
7+
function ModalCloseButton({ onClose }: ModalCloseButtonProps) {
8+
return (
9+
<S.ModalCloseButton onClick={onClose}>
10+
<XMarkIcon />
11+
</S.ModalCloseButton>
12+
);
13+
}
14+
15+
export default ModalCloseButton;

src/components/common/title/Title.styled.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import { TitleProps } from './Title';
44
export const Container = styled.h1<Omit<TitleProps, 'children'>>`
55
font-size: ${({ theme, size }) => theme.heading[size].fontSize};
66
color: ${({ theme }) => theme.color.primary};
7+
display: -webkit-box;
8+
-webkit-line-clamp: 1;
9+
-webkit-box-orient: vertical;
10+
text-overflow: ellipsis;
11+
overflow: hidden;
712
813
@media screen and ${({ theme }) => theme.mediaQuery.tablet} {
914
font-size: ${({ theme, size }) => theme.heading[size].tabletFontSize};

src/components/manageProjects/applicantList/ApplicantItem.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect, useRef } from 'react';
12
import { ApplicantInfo } from '../../../models/applicant';
23
import * as S from './ApplicantItem.styled';
34

@@ -13,9 +14,21 @@ function ApplicantItem({
1314
onClick,
1415
}: ApplicantItemProps) {
1516
const isSelected = selectedApplicant === applicantData.userId;
17+
const itemRef = useRef<HTMLButtonElement>(null);
18+
19+
useEffect(() => {
20+
if (isSelected && itemRef.current) {
21+
itemRef.current.scrollIntoView({
22+
behavior: 'smooth',
23+
block: 'nearest',
24+
});
25+
}
26+
}, [isSelected]);
27+
1628
return (
1729
<>
1830
<S.Button
31+
ref={itemRef}
1932
$isSelected={isSelected}
2033
onClick={() => onClick(applicantData.userId)}
2134
$passStatus={applicantData.status}

src/components/manageProjects/applicantList/ApplicantList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ function ApplicantList({
1616
<S.Container>
1717
{applicantsData.map((data) => (
1818
<ApplicantItem
19+
key={data.userId}
1920
selectedApplicant={selectedApplicant}
2021
onClick={onClick}
21-
key={data.userId}
2222
applicantData={data}
2323
/>
2424
))}

src/components/manageProjects/passNonPassList/PassNonPassItem.styled.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const ItemWrapper = styled.li`
2121
export const NickName = styled.p`
2222
font-size: ${({ theme }) => theme.heading.small.fontSize};
2323
font-weight: 400;
24+
cursor: pointer;
2425
2526
@media ${({ theme }) => theme.mediaQuery.tablet} {
2627
font-size: ${({ theme }) => theme.heading.small.tabletFontSize};

src/components/manageProjects/passNonPassList/PassNonPassItem.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,26 @@ import * as S from './PassNonPassItem.styled';
77
interface PassNonPassItemProps {
88
userInfo: ApplicantInfo;
99
projectData: ProjectDetailExtended;
10-
onClick: ({ status, userId }: useMutationParams) => void;
10+
hanldeStatus: ({ status, userId }: useMutationParams) => void;
11+
handleUserInfo: (userId: number) => void;
1112
}
1213

1314
function PassNonPassItem({
1415
userInfo,
15-
onClick,
16+
hanldeStatus,
1617
projectData,
18+
handleUserInfo,
1719
}: PassNonPassItemProps) {
1820
return (
1921
<S.ItemWrapper>
20-
<S.NickName>{userInfo.User.nickname}</S.NickName>
22+
<S.NickName onClick={() => handleUserInfo(userInfo.userId)}>
23+
{userInfo.User.nickname}
24+
</S.NickName>
2125
<DeleteButton
2226
disabled={projectData.isDone}
23-
onClick={() => onClick({ status: 'WAITING', userId: userInfo.userId })}
27+
onClick={() =>
28+
hanldeStatus({ status: 'WAITING', userId: userInfo.userId })
29+
}
2430
/>
2531
</S.ItemWrapper>
2632
);

src/components/manageProjects/passNonPassList/PassNonPassList.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useNavigate } from 'react-router-dom';
12
import { useMutationParams } from '../../../hooks/usePassNonPassMutation';
23
import { ApplicantInfo } from '../../../models/applicant';
34
import { ProjectDetailExtended } from '../../../models/projectDetail';
@@ -7,20 +8,26 @@ import * as S from './PassNonPassList.styled';
78
interface PassNonPassListProps {
89
passNonPassListData: ApplicantInfo[];
910
projectData: ProjectDetailExtended;
10-
onClick: ({ status, userId }: useMutationParams) => void;
11+
handleStatus: ({ status, userId }: useMutationParams) => void;
1112
}
1213

1314
function PassNonPassList({
1415
passNonPassListData,
1516
projectData,
16-
onClick,
17+
handleStatus,
1718
}: PassNonPassListProps) {
19+
const navigate = useNavigate();
20+
const handleUserInfo = (userId: number) => {
21+
navigate(`/manage/${projectData.id}?userId=${userId}`);
22+
};
23+
1824
return (
1925
<S.Wrapper>
2026
{passNonPassListData.map((data) => (
2127
<PassNonPassItem
2228
key={data.userId}
23-
onClick={onClick}
29+
handleUserInfo={handleUserInfo}
30+
hanldeStatus={handleStatus}
2431
userInfo={data}
2532
projectData={projectData}
2633
/>

src/hooks/useApplicantInfo.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { getApplicantInfo } from '../api/applicant.api';
2-
import { useState } from 'react';
2+
import { useEffect, useState } from 'react';
33
import { useQuery } from '@tanstack/react-query';
44
import { applicantKey } from './queries/keys';
5+
import { useLocation } from 'react-router-dom';
56

67
export const useApplicantInfo = (projectId: number) => {
78
const [selectedApplicant, setSelectedUser] = useState<number | null>(null);
9+
const location = useLocation();
10+
const userId = new URLSearchParams(location.search).get('userId');
811

912
const { data } = useQuery({
1013
queryKey: [applicantKey.info, projectId, selectedApplicant],
@@ -14,8 +17,12 @@ export const useApplicantInfo = (projectId: number) => {
1417
});
1518

1619
const handleSelectedApplicant = (userId: number) => {
17-
setSelectedUser(userId);
20+
if (userId) setSelectedUser(userId);
1821
};
1922

23+
useEffect(() => {
24+
handleSelectedApplicant(Number(userId));
25+
}, [location.search]);
26+
2027
return { applicantInfo: data, selectedApplicant, handleSelectedApplicant };
2128
};

0 commit comments

Comments
 (0)