1. 그룹화 및 자동 채번
2. 멀티 드래그
DraftTypeField.js
ㄴ DraftBody.js
import { useState } from 'react';
import { message } from 'antd';
import DraftHeader from './draft-header';
import StyledDraftTypeField from './styled';
import DraftBody from './draft-body';
export const DraftTypeField = ({ onChange, value: userList, pageMode }) => {
const [selectedUsers, setSelectedUsers] = useState([]);
const [isOpenBody, setIsOpenBody] = useState(false);
const onChangeOpen = () => {
setIsOpenBody(!isOpenBody);
};
const onChangeUserlist = (list) => {
setIsOpenBody(true);
onChange(list);
};
const handleClick = (_user) => {
setSelectedUsers([_user]);
};
const selectRange = (startIndex, endIndex) => {
const start = Math.min(startIndex, endIndex);
const end = Math.max(startIndex, endIndex);
const selectedRange = userList.slice(start, end + 1);
setSelectedUsers(selectedRange);
};
const clearSelection = () => {
setSelectedUsers([]);
};
const sortingUserList = (_userList, selectedList) => {
const list = [..._userList];
let sortSq = 0;
let flag = false;
list.forEach((user) => {
if (selectedList?.includes(user.ACNT_ID) || user.DRAFT_TYPE === 'P') {
user.SORT_SQ = sortSq;
user.DRAFT_TYPE = 'P';
flag = true;
} else {
if (flag) {
sortSq++;
}
flag = false;
user.SORT_SQ = sortSq++;
}
});
return list;
};
const onParallel = () => {
if (selectedUsers.length > 1) {
const fSelectedUsers = selectedUsers.filter((user) => user.DRAFT_TYPE !== 'D');
const parallelACNTIDs = fSelectedUsers.map((user) => user.ACNT_ID);
const updatedUserList = sortingUserList(userList, parallelACNTIDs);
onChange(updatedUserList);
} else {
message.info('선택된 직원이 2명이상이어야 합니다.');
}
};
const onUnParallel = () => {
if (selectedUsers.length > 0) {
const fSelectedUsers = selectedUsers.filter((user) => user.DRAFT_TYPE !== 'D');
const selectedAcntIds = fSelectedUsers.map((user) => user.ACNT_ID);
// 기안자가 아닌 사용자들의 DRAFT_TYPE를 'A'로 변경
const updatedUserList = userList.map((user) => ({
...user,
DRAFT_TYPE: selectedAcntIds.includes(user.ACNT_ID) ? 'A' : user.DRAFT_TYPE,
}));
const _userList = sortingUserList(updatedUserList, []);
onChange(_userList);
} else {
message.info('선택된 직원이 없습니다.');
}
};
const onDragEnd = (result) => {
const updateList = sortingUserList(result, []);
onChange(updateList);
};
return (
<StyledDraftTypeField>
<DraftHeader
userList={userList}
onChangeOpen={onChangeOpen}
isOpenBody={isOpenBody}
onChangeUserlist={onChangeUserlist}
onParallel={onParallel}
onUnParallel={onUnParallel}
pageMode={pageMode}
/>
<DraftBody
isOpenBody={isOpenBody}
userList={userList}
selectedUsers={selectedUsers}
selectRange={selectRange}
clearSelection={clearSelection}
handleClick={handleClick}
pageMode={pageMode}
onDragEnd={onDragEnd}
/>
</StyledDraftTypeField>
);
};
import React, { useEffect, useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import StyeldDraftBody from './styled';
import update from 'immutability-helper';
import { message } from 'antd';
const DraftBody = ({
isOpenBody,
userList,
selectedUsers,
selectRange,
clearSelection,
handleClick,
pageMode,
onDragEnd,
}) => {
const [selectedSortSq, setSelectedSortSq] = useState(null);
const [selectedList, setSelectedList] = useState([]);
const handleItemClick = (sortSq) => {
setSelectedSortSq(sortSq);
setSelectedList(userList.filter((user) => user.SORT_SQ === sortSq));
};
const _onDragEnd = (_result) => {
if (!_result.destination) {
return;
}
const dragIdx = _result.source.index;
const destIdx = _result.destination.index;
if (destIdx === 0) {
message.info('기안자는 바꿀 수 없습니다.');
return;
}
const resultList = [...userList];
if ([0, 1].includes(selectedList.length)) {
const nTab = userList[dragIdx];
resultList.splice(dragIdx, 1);
resultList.splice(destIdx, 0, nTab);
} else {
selectedList.forEach((user) => {
const idx = resultList.findIndex((f) => f.ACNT_ID === user.ACNT_ID);
resultList.splice(idx, 1);
resultList.splice(destIdx, 0, user);
});
}
onDragEnd(resultList);
};
return (
<StyeldDraftBody>
<div className={`draft-body ${isOpenBody ? 'open' : ''}`}>
<DragDropContext onDragEnd={_onDragEnd}>
<Droppable droppableId="droppable">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{userList &&
userList.length > 0 &&
userList.map((user, i) => {
//draft_type을 선언
//type : 기안 / 병렬합의 / (결재 / 합의 / 통보 )
const { ACNT_NM, DEPT_NM, PSTN_NM, DRAFT_TYPE, SORT_SQ } = user || {};
const isSelected = selectedUsers.includes(user);
const handleUserClick = (event) => {
if (!event.shiftKey) {
handleClick(user);
} else {
const lastIndex = userList.findIndex((u) => u === selectedUsers[selectedUsers.length - 1]);
selectRange(lastIndex, i);
}
};
return (
<Draggable key={`i-${user.ACNT_ID}`} draggableId={`i-${user.ACNT_ID}`} index={i}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
onMouseDown={() => handleItemClick(user.SORT_SQ)}
style={{
background:
selectedSortSq === user.SORT_SQ && user.DRAFT_TYPE === 'P' ? 'lightblue' : 'white',
...provided.draggableProps.style,
}}
>
<div
className={`user ${isSelected ? 'selected' : ''}`}
key={i}
onClick={handleUserClick}
onDoubleClick={clearSelection}
>
<div className="user-no">{SORT_SQ}</div>
<div className="user-state">{DRAFT_TYPE}</div>
<div className="user-nm">
{ACNT_NM} / {DEPT_NM} / {PSTN_NM}
</div>
</div>
</div>
)}
</Draggable>
);
})}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
</StyeldDraftBody>
);
};
export default DraftBody;
const sortingUserList = (_userList, selectedList) => {
const list = [..._userList];
let sortSq = 0;
let flag = false;
list.forEach((user) => {
if (selectedList?.includes(user.ACNT_ID) || user.DRAFT_TYPE === 'P') {
user.SORT_SQ = sortSq;
user.DRAFT_TYPE = 'P';
flag = true;
} else {
if (flag) {
sortSq++;
}
flag = false;
user.SORT_SQ = sortSq++;
}
});
return list;
};
flag를 걸어서 조건식이 끝난 뒤의 채번도 ++ 할 수 있게 한다.
const handleItemClick = (sortSq) => {
setSelectedSortSq(sortSq);
setSelectedList(userList.filter((user) => user.SORT_SQ === sortSq));
};
다중 선택이 아닌 조건에 의한 여러 값을 자동으로 선택되게 했다.
style={{ background: selectedSortSq === user.SORT_SQ &&
user.DRAFT_TYPE === 'P' ? 'lightblue' : 'white',
...provided.draggableProps.style,}}
선택된 항목들은 background를 lightblue로 변경하여 구분하였다.
const resultList = [...userList];
if ([0, 1].includes(selectedList.length)) {
const nTab = userList[dragIdx];
resultList.splice(dragIdx, 1);
resultList.splice(destIdx, 0, nTab);
} else {
selectedList.forEach((user) => {
const idx = resultList.findIndex((f) => f.ACNT_ID === user.ACNT_ID);
resultList.splice(idx, 1);
resultList.splice(destIdx, 0, user);
});
}
선택된 항목이 없거나 1개일 때는 일반적인 드래그를 실행
선택된 항목이 2개 이상일 때는 선택된 항목의 배열을 돌면서 계속 변경해준다.
끝