Skip to content

Commit

Permalink
Merge pull request #194 from BCSDLab/feat/position-search
Browse files Browse the repository at this point in the history
[직책관리] 이름검색, 동명이인처리, API변경 반영
  • Loading branch information
MinGu-Jeong authored Oct 8, 2024
2 parents 0289cc0 + e4ca2fc commit dd9dd54
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 54 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
4 changes: 2 additions & 2 deletions src/api/jobs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export const putJobs = ({
};

export const postJobs = ({
memberId, type, startYear, startMonth, endYear, endMonth,
email, type, startYear, startMonth, endYear, endMonth,
}: PostJob) => {
return accessClient.post<PostJob>(`/jobs?memberId=${memberId}&type=${type}&startYear=${startYear}&startMonth=${startMonth}&endYear=${endYear}&endMonth=${endMonth}`);
return accessClient.post<PostJob>(`/jobs?email=${email}&type=${type}&startYear=${startYear}&startMonth=${startMonth}&endYear=${endYear}&endMonth=${endMonth}`);
};

export const deleteJobs = (jobId: number) => {
Expand Down
126 changes: 75 additions & 51 deletions src/component/modal/createJobModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { useState } from 'react';
import { usePostJobs } from 'query/jobs';
import { useGetMembers } from 'query/members';
import { useSnackBar } from 'ts/useSnackBar';
import { Member } from 'model/member';
import * as S from './style';
import SearchNameModal from '../searchNameModal';

interface CreateJobModalProps {
open: boolean;
Expand All @@ -18,6 +20,7 @@ interface InitialInfo {
startMonth: string;
endYear: string;
endMonth: string;
email: string;
}

export default function CreateJobModal({ open, onClose, setIsSuccess }: CreateJobModalProps) {
Expand All @@ -28,11 +31,13 @@ export default function CreateJobModal({ open, onClose, setIsSuccess }: CreateJo
startMonth: '',
endYear: '',
endMonth: '',
email: '',
};
const [info, setInfo] = useState<InitialInfo>(initialInfo);
const { data: members } = useGetMembers({ pageIndex: 0, pageSize: 1000, trackId: null });
const postJobsMutation = usePostJobs({ setIsSuccess, onClose });
const openSnackBar = useSnackBar();
const [nameModalOpen, setNameModalOpen] = useState(false);

const handleInfoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInfo({
Expand All @@ -43,6 +48,7 @@ export default function CreateJobModal({ open, onClose, setIsSuccess }: CreateJo

const handleCreateInfoClick = () => {
const memberId = members?.content.find((member) => member.name === info.name)?.id;
const email = members?.content.find((member) => member.email === info.email)?.email;
if (memberId) {
if (info.startYear === '' || info.startMonth === '' || info.endYear === '' || info.endMonth === '') {
openSnackBar({ type: 'error', message: '빈 칸을 채워주세요.' });
Expand All @@ -54,7 +60,7 @@ export default function CreateJobModal({ open, onClose, setIsSuccess }: CreateJo
openSnackBar({ type: 'error', message: '시작 월이 종료 월보다 늦을 수 없습니다.' });
} else {
postJobsMutation.mutate({
memberId,
email,
type: info.type,
startYear: Number(info.startYear),
startMonth: Number(info.startMonth),
Expand All @@ -70,62 +76,80 @@ export default function CreateJobModal({ open, onClose, setIsSuccess }: CreateJo
setInfo(initialInfo);
};

const handleSelectMember = (member: Member) => {
setInfo({
...info,
name: member.name,
email: member.email,
});
setNameModalOpen(false);
};

return (
<Modal
open={open}
onClose={handleCloseModal}
>
<div css={S.modal}>
<h2 css={S.modalTitle}>직책 생성</h2>
<div css={S.modalContent}>
<TextField
label="이름"
name="name"
value={info?.name}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책명"
name="type"
value={info?.type}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 시작 연도"
name="startYear"
value={info?.startYear}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 시작 월"
name="startMonth"
value={info?.startMonth}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 종료 연도"
name="endYear"
value={info?.endYear}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 종료 월"
name="endMonth"
value={info?.endMonth}
onChange={handleInfoChange}
css={S.textField}
/>
</div>
<div css={S.buttonWrapper}>
<Button variant="contained" onClick={handleCreateInfoClick}>저장</Button>
<Button variant="outlined" onClick={handleCloseModal} css={S.closeButton}>닫기</Button>
<>
<div css={S.modal}>
<h2 css={S.modalTitle}>직책 생성</h2>
<div css={S.modalContent}>
<TextField
label="이름"
name="name"
value={info?.name}
onClick={() => setNameModalOpen(true)}
css={S.textField}
/>
<TextField
label="직책명"
name="type"
value={info?.type}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 시작 연도"
name="startYear"
value={info?.startYear}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 시작 월"
name="startMonth"
value={info?.startMonth}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 종료 연도"
name="endYear"
value={info?.endYear}
onChange={handleInfoChange}
css={S.textField}
/>
<TextField
label="직책 종료 월"
name="endMonth"
value={info?.endMonth}
onChange={handleInfoChange}
css={S.textField}
/>
</div>
<div css={S.buttonWrapper}>
<Button variant="contained" onClick={handleCreateInfoClick}>저장</Button>
<Button variant="outlined" onClick={handleCloseModal} css={S.closeButton}>닫기</Button>
</div>
</div>
</div>
{nameModalOpen && (
<SearchNameModal
open={nameModalOpen}
onClose={() => setNameModalOpen(false)}
onSelect={handleSelectMember}
/>
)}
</>
</Modal>
);
}
85 changes: 85 additions & 0 deletions src/component/modal/searchNameModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {
useState, useEffect, useCallback, memo, useMemo,
} from 'react';
import {
Typography, Box, List, TextField, ListItemText, Modal, ListItemButton,
} from '@mui/material';
import { useSearchMembers } from 'query/members';
import { Member } from 'model/member';
import * as S from './style';

interface SearchMemberModalProps {
open: boolean;
onClose: () => void;
onSelect: (member: Member) => void;
}

function SearchNameModal({
open, onClose, onSelect,
}: SearchMemberModalProps) {
const [searchQuery, setSearchQuery] = useState('');
const [searchResults, setSearchResults] = useState<Member[]>([]);

const { data: membersResult } = useSearchMembers({
pageIndex: 0, pageSize: 1000, name: searchQuery,
});

useEffect(() => {
if (membersResult) {
setSearchResults(membersResult.content);
} else {
setSearchResults([]);
}
}, [membersResult]);

const handleSearchChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setSearchQuery(e.target.value);
}, []);

const renderSearchResults = useMemo(() => (
searchResults
.filter((member) => (member.isDeleted === false && member.memberType === 'REGULAR'))
.map((member) => (
<ListItemButton
key={member.id}
sx={S.listButton}
onClick={() => {
onSelect(member);
onClose();
}}
>
<ListItemText primary={`${member.name} (${member.track.name})`} />
</ListItemButton>
))
), [searchResults, onSelect, onClose]);

return (
<Modal
open={open}
onClose={onClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={S.modalView}>
<Typography id="modal-modal-title" variant="h6" component="h2">
추가할 사용자를 검색하세요
</Typography>
<TextField
type="text"
variant="outlined"
value={searchQuery}
onChange={handleSearchChange}
fullWidth
autoFocus
/>
<Box sx={S.searchMemberResult}>
<List>
{renderSearchResults}
</List>
</Box>
</Box>
</Modal>
);
}

export default memo(SearchNameModal);
27 changes: 27 additions & 0 deletions src/component/modal/searchNameModal/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const modalView = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
borderRadius: 1,
p: 4,
};

export const searchMemberResult = {
height: 300,
overflow: 'auto',
};

export const listButton = {
border: 1,
borderColor: 'gray',
borderRadius: 2,
marginBottom: 1,
'&:hover': {
backgroundColor: '#D6F3FE',
},
};
3 changes: 2 additions & 1 deletion src/model/job.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export interface PostJob {
memberId: number;
memberId?: number;
email?: string;
type: string;
startYear: number;
startMonth: number;
Expand Down

0 comments on commit dd9dd54

Please sign in to comment.