Files
operationSystem-front/src/components/DataManage/UserMailInfo.js
bcjang 9be5bb388a data 정보 수정
우편 내용 복사 기능
우편 코드 정리
유저 인벤토리 아이템 삭제 제거
2025-05-15 17:49:45 +09:00

399 lines
10 KiB
JavaScript

import { useState, Fragment, useEffect, memo } from 'react';
import styled from 'styled-components';
import MailDetailModal from '../../components/DataManage/MailDetailModal';
import { SelectInput, TextInput } from '../../styles/Components';
import { UserMailDelete, UserMailItemDelete, UserMailView } from '../../apis';
import { useTranslation } from 'react-i18next';
import CustomConfirmModal from '../common/modal/CustomConfirmModal';
import { authType, ivenTabType, opMailType } from '../../assets/data';
import { useRecoilValue } from 'recoil';
import { authList } from '../../store/authList';
import { convertKTC } from '../../utils';
import { TableSkeleton } from '../Skeleton/TableSkeleton';
import { opPickupType, opReadType, opYNType } from '../../assets/data/options';
import { useDynamoDBPagination, useModal } from '../../hooks/hook';
import { DynamoPagination } from '../common';
import { useLoading } from '../../context/LoadingProvider';
import { useAlert } from '../../context/AlertProvider';
import { alertTypes } from '../../assets/data/types';
const ConfirmChild = memo(({ maxCount }) => {
const { t } = useTranslation();
const [localCount, setLocalCount] = useState('1');
const {showToast} = useAlert();
const handleChange = (e) => {
let value = e.target.value;
if (value === '0' || value === '-0') {
value = '1';
} else if (value < 0) {
value = Math.abs(value).toString();
} else if(Number(value) > maxCount) {
showToast('DEL_COUNT_CHECK', {type: alertTypes.warning});
value = maxCount.toString();
}
setLocalCount(value);
};
return(
<InputItem>
<p>{t('DEL_COUNT_CONFIRM', {count: maxCount})}</p>
<TextInput
id="user-mail-item-count-input"
placeholder="수량"
type="number"
value={localCount}
onChange={handleChange}
width="200px"
/>
</InputItem>
);
});
const UserMailInfo = ({ userInfo }) => {
const token = sessionStorage.getItem('token');
const authInfo = useRecoilValue(authList);
const {withLoading} = useLoading();
const {showModal, showToast} = useAlert();
// 받은 우편, 보낸 우편
const [option, setOption] = useState('RECEIVE');
const [detail, setDetail] = useState({ title: '', content: '', item_list: [], mail_guid: '' });
const [deleteSelected, setDeleteSelected] = useState({});
const [authDelete, setAuthDelete] = useState(false);
const {
modalState,
handleModalView,
handleModalClose
} = useModal({
detail: 'hidden',
deleteItem: 'hidden'
});
const fetchMailData = async (page, startKey) => {
const params = {
mail_type: option,
guid: userInfo.guid,
page_key: startKey
};
return await UserMailView(token, params);
};
const {
data: dataList,
loading,
pagination,
fetchPage,
goToNextPage,
goToPrevPage,
resetPagination
} = useDynamoDBPagination(fetchMailData);
useEffect(() => {
resetPagination();
fetchPage(1);
}, [option]);
useEffect(() => {
setAuthDelete(authInfo.auth_list.some(auth => auth.id === authType.userSearchDelete));
}, [authInfo]);
const handleDetail = (title, content, itmeList, mail_guid) => {
setDetail({ title: title, content: content, item_list: itmeList, mail_guid: mail_guid });
};
const handleModalSubmit = async (type, param = null) => {
let params;
switch (type) {
case "detail":
showModal('USER_MAIL_DEL_CONFIRM', {
type: alertTypes.confirm,
onConfirm: () => handleModalSubmit('deleteSubmit')
});
break;
case "deleteSubmit":
params = {}
params.type = option;
params.guid = userInfo.guid;
params.mail_guid = detail.mail_guid;
await withLoading(async () => {
return await UserMailDelete(token, params);
}).then(data => {
if(data.result === "SUCCESS") {
showToast('DEL_COMPLETE', {type: alertTypes.success});
}else{
showToast(data.data.message, {type: alertTypes.error});
}
}).catch(e => {
showToast(e, {type: alertTypes.error});
});
break;
case "deleteItem":
setDeleteSelected(param);
handleModalView('deleteItem');
break;
case "deleteItemSubmit":
//랜더링 문제로 dom에서 값을 찾아 가져온다.
const inputElement = document.getElementById("user-mail-item-count-input");
if(inputElement === null) showToast('INPUT_VALUE_ERROR',{type: alertTypes.error});
const count = inputElement.value;
params = {}
params.type = option;
params.guid = userInfo.guid;
params.mail_guid = detail.mail_guid;
params.item_id = deleteSelected.item_id;
params.parrent_count = deleteSelected.count;
params.count = count;
await withLoading(async () => {
return await UserMailItemDelete(token, params);
}).then(data => {
if(data.result === "SUCCESS") {
if(deleteSelected.count <= count){
const item_idx = detail.item_list.findIndex(item => item.item_id === params.item_id);
if(item_idx >= 0) {
detail.item_list.splice(item_idx, 1);
}
}else{
deleteSelected.count = deleteSelected.count - count;
}
showToast('DEL_ITEM_COMPLETE', {type: alertTypes.success});
}else{
showToast(data.data.message, {type: alertTypes.error});
}
}).catch(e => {
showToast(e, {type: alertTypes.error});
}).finally(() => {
handleModalClose('deleteItem');
fetchPage(pagination.currentPage);
});
break;
}
}
return (
loading ? <TableSkeleton count={10}/> :
<>
<SelectContainer>
<SelectInput
value={option}
onChange={e => {
setOption(e.target.value);
}}>
{opMailType.map((data, index) => (
<option key={index} value={data.value}>
{data.name}
</option>
))}
</SelectInput>
<DynamoPagination
pagination={pagination}
onNextPage={goToNextPage}
onPrevPage={goToPrevPage}
/>
</SelectContainer>
{option === 'RECEIVE' && (
<>
<UserTableWrapper>
<UserDefaultTable>
<thead>
<tr>
<th width="170">수신일자</th>
<th width="200">발송자</th>
<th width="300">우편 제목</th>
<th width="80">상태</th>
<th width="100">첨부 아이템</th>
<th width="80">수령</th>
<th width="80">시스템 우편</th>
</tr>
</thead>
<tbody>
{dataList?.mail_list?.map((mail, idx) => {
return (
<tr key={idx}>
<td>{convertKTC(mail.create_time)}</td>
<td>{mail.sender_nickname}</td>
<td>
<MailLink
onClick={e => {
e.preventDefault();
handleModalView('detail');
handleDetail(mail.title, mail.content, mail.item_list, mail.mail_guid);
}}>
{mail.title}
</MailLink>
</td>
<td>{opReadType.find(type => type.value === mail.status).name}</td>
<td>{opYNType.find(type => type.value === (mail.item_list.length > 0)).name}</td>
<td>{opPickupType.find(type => type.value === mail.is_get_item).name}</td>
<td>{opYNType.find(type => type.value === mail.is_system_mail).name}</td>
</tr>
);
})}
</tbody>
</UserDefaultTable>
</UserTableWrapper>
</>
)}
{option === 'SEND' && (
<>
<UserTableWrapper>
<UserDefaultTable>
<thead>
<tr>
<th width="170">발송 일자</th>
<th width="200">수신자</th>
<th width="300">우편 제목</th>
<th width="120">첨부 아이템</th>
</tr>
</thead>
<tbody>
{dataList && dataList.mail_list &&
dataList.mail_list.map((mail, idx) => {
return (
<tr key={idx}>
<td>{convertKTC(mail.create_time)}</td>
<td>{mail.receiver_nickname}</td>
<td>
<MailLink
onClick={e => {
e.preventDefault();
handleModalView('detail');
handleDetail(mail.title, mail.content, mail.item_list, mail.mail_guid);
}}>
{mail.title}
</MailLink>
</td>
<td>{mail.item_list.length > 0 ? 'Y' : 'N'}</td>
</tr>
);
})}
</tbody>
</UserDefaultTable>
</UserTableWrapper>
</>
)}
{/*상세*/}
<MailDetailModal
mailModal={modalState.detailModal}
handleClick={() => handleModalClose('detail')}
setDetail={setDetail}
content={detail}
handleDelete={() => handleModalSubmit('detail')}
handleItemDelete={(param) => handleModalSubmit('deleteItem', param)}
authDelete={authDelete}
/>
{/*메일 아이템 삭제 모달*/}
<CustomConfirmModal
ChildView={() => (
<ConfirmChild
maxCount={deleteSelected.count}
/>
)}
view={modalState.deleteItemModal}
handleSubmit={() => handleModalSubmit('deleteItemSubmit')}
handleCancel={() => handleModalClose('deleteItem')}
handleClose={() => handleModalClose('deleteItem')}
/>
</>
);
};
export default UserMailInfo;
const UserDefaultTable = styled.table`
border: 1px solid #e8eaec;
border-top: 1px solid #000;
font-size: 14px;
margin-bottom: 40px;
th {
background: #efefef;
font-weight: 700;
}
th,
td {
padding: 12px;
text-align: center;
border-left: 1px solid #e8eaec;
vertical-align: middle;
}
td {
background: #fff;
border-bottom: 1px solid #e8eaec;
word-break: break-all;
}
button {
height: 24px;
font-size: 13px;
}
`;
const QuestTable = styled(UserDefaultTable)`
tbody {
td {
padding: 9px 12px;
}
}
`;
const UserTableWrapper = styled.div`
width: 100%;
overflow: auto;
margin-bottom: 40px;
${UserDefaultTable}, ${QuestTable} {
margin-bottom: 0;
}
&::-webkit-scrollbar {
height: 4px;
}
&::-webkit-scrollbar-thumb {
background: #666666;
}
&::-webkit-scrollbar-track {
background: #d9d9d9;
}
`;
const MailLink = styled.div`
color: #61a2d0;
text-decoration: underline;
cursor: pointer;
`;
const InputItem = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center; /* 수평 중앙 정렬 */
gap: 10px;
${TextInput} {
height: 35px;
font-size: 14px;
width: 100px;
padding: 10px 20px;
}
`;
const SelectContainer = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
select {
height: 30px;
}
`;