Skip to content

Commit

Permalink
Merge pull request #100 from tteokbokki-master/feat/resumeViewer
Browse files Browse the repository at this point in the history
Feat/#90 이λ ₯μ„œ μ—΄λžŒ νŽ˜μ΄μ§€ κ΅¬ν˜„
  • Loading branch information
YIMSEBIN authored Nov 6, 2024
2 parents b6e44a3 + b57a8b0 commit c62bbfc
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ const Section = styled.div`
align-items: center;
margin-bottom: 52px;
`;
```
```
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/apis/apiPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const APIPath = {
registerCompany: `${BASE_URL}/company`,
apply: '/api/application/',
recruitmentsDetail: '/api/recruitments/:postId',
getApplicantProfile: '/api/resumes/:resumeId/:applyId',
closeRecruitment: `${BASE_URL}/recruitment/hiringClose/:recruitmentId`,
};

Expand All @@ -27,6 +28,8 @@ export const getDynamicAPIPath = {
APIPath.getMyApplicants.replace(':recruitmentId', recruitmentId.toString()),
getForeigner: (userId: number) => APIPath.getForeigner.replace(':userId', userId.toString()),
recruitmentsDetail: (postId: string) => APIPath.recruitmentsDetail.replace(':postId', postId.toString()),
getApplicantProfile: (resumeId: number, applyId: number) =>
APIPath.getApplicantProfile.replace(':resumeId', resumeId.toString()).replace(':applyId', applyId.toString()),
closeRecruitment: (recruitmentId: number) =>
APIPath.closeRecruitment.replace(':recruitmentId', recruitmentId.toString()),
};
19 changes: 19 additions & 0 deletions src/apis/applicants/hooks/useGetProfileInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { getDynamicAPIPath } from '@/apis/apiPath';
import { clientInstance } from '@/apis/instance';
import { useQuery } from '@tanstack/react-query';

type IdProps = {
resumeId: number;
applyId: number;
};

export const getProfileInfo = async ({ resumeId, applyId }: IdProps) => {
const response = await clientInstance.get(getDynamicAPIPath.getApplicantProfile(resumeId, applyId));
return response.data;
};

export const useGetProfileInfo = ({ resumeId, applyId }: IdProps) =>
useQuery({
queryKey: [getDynamicAPIPath.getApplicantProfile(resumeId, applyId)],
queryFn: () => getProfileInfo({ resumeId, applyId }),
});
18 changes: 18 additions & 0 deletions src/apis/applicants/mocks/getApplicantProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { http, HttpResponse } from 'msw';
import { APIPath } from '@/apis/apiPath';

const mockData = {
applicantName: 'μž„μ„ΈλΉˆ',
address: 'μΆ©λ‚¨λŒ€ν•™κ΅',
phoneNumber: '010-1111-1111',
career: `μΉ΄νŽ˜μ—μ„œ 1λ…„ μ•Œλ°”ν–ˆμŠ΅λ‹ˆλ‹€. ν΄λŸ½μ—μ„œ 30λ…„ κ·Όλ¬΄ν–ˆμŠ΅λ‹ˆλ‹€.`,
koreanLanguageLevel: 'κ³ κΈ‰',
introduction: `맑은 업무에 항상 μ΅œμ„ μ„ λ‹€ν•˜λŠ” μΈμž¬μž…λ‹ˆλ‹€. μ•ˆλ…•ν•˜μ„Έμš©μ•ˆλ…•ν•˜μ„Έμš©μ•ˆλ…•ν•˜μ„Έμš©μ•ˆλ…•ν•˜μ„Έμš©μ•ˆλ…•ν•˜μ„Έμš©μ•ˆλ…•ν•˜μ„Έμš©`,
motivation: '돈',
};

export const getProfileInfoHandler = [
http.get(APIPath.getApplicantProfile, () => {
return HttpResponse.json(mockData);
}),
];
2 changes: 2 additions & 0 deletions src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { postApplyMockHandler } from '@apis/apply/postApply.mock';
import { recruitmentsDetailMockHandler } from '@apis/recruitmentsDetail/recruitmentsDetailMockHandler';
import { registerCompanyMockHandler } from '@/apis/registerCompany/registerCompany.mock';
import { contractsMockHandler } from '@/apis/contract/mock/contract.mock';
import { getProfileInfoHandler } from '@/apis/applicants/mocks/getApplicantProfile';
import { closeRecruitmentMockHandler } from '@/apis/recruitments/mocks/closeRecruitmentMockHandler';

export const handlers = [
Expand All @@ -29,5 +30,6 @@ export const handlers = [
...recruitmentsDetailMockHandler,
...registerCompanyMockHandler,
...contractsMockHandler,
...getProfileInfoHandler,
...closeRecruitmentMockHandler,
];
60 changes: 60 additions & 0 deletions src/pages/applicantsPage/ApplicantList/ApplicantProfile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useGetProfileInfo } from '@/apis/applicants/hooks/useGetProfileInfo';
import { Flex, Typo } from '@/components/common';
import styled from '@emotion/styled';
import { Spinner } from '@/components/common';

type ProfileInfoProps = {
title: string;
content: string;
};
function ProfileInfo({ title, content }: ProfileInfoProps) {
return (
<>
<Flex>
<Flex direction="column" gap={{ y: '20px' }}>
<Typo bold={true}>{title}</Typo>
<Typo>{content}</Typo>
</Flex>
</Flex>
<Divider />
</>
);
}

export default function ApplicantProfile({ resumeId, applyId }: { resumeId: number; applyId: number }) {
const { data, isLoading } = useGetProfileInfo({ resumeId, applyId });

if (isLoading) {
return <Spinner />;
}
return (
<Flex css={{ padding: '10px', width: '100%' }} direction="column">
<Typo bold={true} size="18px">
{data.applicantName}λ‹˜μ˜ μ§€μ›μ„œμž…λ‹ˆλ‹€.
</Typo>
<Flex gap={{ x: '10px' }} css={{ marginTop: '20px' }}>
<Flex direction="column" gap={{ y: '5px' }} css={{ flex: 2 }}>
<Typo>μ—°λ½μ²˜</Typo>
<Typo>μ£Όμ†Œ</Typo>
</Flex>
<Flex direction="column" gap={{ y: '5px' }} css={{ flex: 8 }}>
<Typo>{data.phoneNumber}</Typo>
<Typo>{data.address}</Typo>
</Flex>
</Flex>
<Divider />
<ProfileInfo title="ν•œκ΅­μ–΄ μ‹€λ ₯" content={data.koreanLanguageLevel} />
<ProfileInfo title="κ²½λ ₯" content={data.career} />
<ProfileInfo title="μžκΈ°μ†Œκ°œμ„œ" content={data.introduction} />
<ProfileInfo title="지원동기" content={data.motivation} />
</Flex>
);
}

const Divider = styled.div`
width: 100%;
height: 1px;
opacity: 0.7;
margin: 20px 0;
background-color: #e9e9e9;
`;
35 changes: 33 additions & 2 deletions src/pages/applicantsPage/ApplicantList/ApplicantsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { Button, Flex, List, Table, Td, Th } from '@/components/common';
import { Button, Flex, List, Table, Td, Th, Modal } from '@/components/common';
import { useState } from 'react';
import ContractModal from './Contract/ContractModal';
import { ApplicantData } from '@/types';
import { buttonGroupStyle, buttonsCellStyle, buttonStyle } from './ApplicantsTable.styles';
import ApplicantProfile from '../ApplicantList/ApplicantProfile';
import useToggle from '@/hooks/useToggle';

type IdProps = {
resumeId: number;
applyId: number;
};
type Props = {
applicantList: ApplicantData[];
};

export default function ApplicantsTable({ applicantList }: Props) {
const [isModalOpen, setIsModalOpen] = useState(false);
const [IdInfo, setIdInfo] = useState<IdProps | null>(null);
const [selectedUserId, setSelectedUserId] = useState<number | null>(null);
const [isToggle, toggle] = useToggle();
const [selectedApplyId, setSelectedApplyId] = useState<number | null>(null);

const openModal = (userId: number, applyId: number) => {
Expand All @@ -25,6 +33,10 @@ export default function ApplicantsTable({ applicantList }: Props) {
setSelectedApplyId(null);
};

const profileOpenModal = ({ resumeId, applyId }: IdProps) => {
setIdInfo((prev) => ({ ...prev, resumeId, applyId }));
toggle();
};
return (
<>
<Table>
Expand All @@ -46,7 +58,12 @@ export default function ApplicantsTable({ applicantList }: Props) {
<Td>{applicant.korean}</Td>
<Td css={buttonsCellStyle}>
<Flex justifyContent="flex-end" alignItems="center" gap={{ x: '20px' }} css={buttonGroupStyle}>
<Button css={buttonStyle}>μ§€μ›μ„œ</Button>
<Button
onClick={() => profileOpenModal({ resumeId: applicant.resumeId, applyId: applicant.applyId })}
css={buttonStyle}
>
μ§€μ›μ„œ
</Button>
<Button css={buttonStyle} onClick={() => openModal(applicant.userId, applicant.applyId)}>
κ³„μ•½ν•˜κΈ°
</Button>
Expand All @@ -60,6 +77,20 @@ export default function ApplicantsTable({ applicantList }: Props) {
{selectedUserId && selectedApplyId && (
<ContractModal isOpen={isModalOpen} close={closeModal} userId={selectedUserId} applyId={selectedApplyId} />
)}
{isToggle && IdInfo && (
<Modal
css={{
width: '100%',
maxWidth: '450px',
'@media (max-width: 480px)': {
width: '90%',
},
}}
textChildren={<ApplicantProfile resumeId={IdInfo.resumeId} applyId={IdInfo.applyId} />}
buttonChildren={<Button onClick={toggle}>λ‹«κΈ°</Button>}
onClose={toggle}
/>
)}
</>
);
}

0 comments on commit c62bbfc

Please sign in to comment.