Browse Source

feat/운항과 관제과 재검토 화면 기능 추가

master
sanguu516 1 month ago
parent
commit
6b598e7321
  1. 14
      src/components/flight/ControlApprovalsTable.js
  2. 32
      src/components/flight/OperationApprovalsTable.js
  3. 208
      src/components/flight/OperationCheckBoxModal.js
  4. 1
      src/containers/flight/ControlApprovalsContainer.js
  5. 4
      src/containers/flight/OperationApprovalsContainer.js

14
src/components/flight/ControlApprovalsTable.js

@ -553,7 +553,7 @@ export default function ControlApprovalsTable(props) {
dispatch( dispatch(
openModal({ openModal({
header: '재검토 사유', header: '재검토 사유',
body: record, body: record.reviewedReason,
type: 'review' type: 'review'
}) })
); );
@ -1208,11 +1208,13 @@ export default function ControlApprovalsTable(props) {
dispatch( dispatch(
updateLaancAprvReview({ planAreaSnoList, reviewedType: 'R' }) updateLaancAprvReview({ planAreaSnoList, reviewedType: 'R' })
).then(() => { ).then(() => {
dispatch( props.handlerSearch(
getLaancAprvList({ props.filterId,
searchStDt: props.startDate, {
searchEndDt: props.endDate startDate: props.startDate,
}) endDate: props.endDate
},
props.filterArea
); );
}); });
setCheckList([]); setCheckList([]);

32
src/components/flight/OperationApprovalsTable.js

@ -1218,32 +1218,6 @@ export default function OperationApprovalsTable(props) {
setCheckData(res); setCheckData(res);
setIsCheckBoxModal(true); setIsCheckBoxModal(true);
// try {
// const planAreaSnoList = [
// ...new Set(
// checkList
// .filter(item => item.startsWith('child_')) // 'child_'로 시작하는 항목 필터링
// .map(item => item.split('_').pop()) // 마지막 언더바 이후의 숫자 추출
// )
// ];
// dispatch(
// updateLaancAprvReview({ planAreaSnoList, reviewedType: 'R' })
// ).then(() => {
// dispatch(
// getLaancAprvList({
// searchStDt: props.startDate,
// searchEndDt: props.endDate
// })
// );
// });
// setCheckList([]);
// } catch (error) {
// return handlerErrorModal(
// '재검토 요청 실패',
// '재검토 요청을 실패하였습니다. 다시 시도해주세요.',
// false
// );
// }
}; };
return ( return (
@ -1266,6 +1240,12 @@ export default function OperationApprovalsTable(props) {
setCheckData={setCheckData} setCheckData={setCheckData}
isCheckBoxModal={isCheckBoxModal} isCheckBoxModal={isCheckBoxModal}
setIsCheckBoxModal={setIsCheckBoxModal} setIsCheckBoxModal={setIsCheckBoxModal}
handlerErrorModal={handlerErrorModal}
handlerSearch={props.handlerSearch}
filterArea={props.filterArea}
filterId={props.filterId}
startDate={props.startDate}
endDate={props.endDate}
/> />
)} )}
<div className='search-download'> <div className='search-download'>

208
src/components/flight/OperationCheckBoxModal.js

@ -6,25 +6,41 @@ import {
ModalFooter ModalFooter
} from '@component/ui'; } from '@component/ui';
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Table, Form, Input } from 'antd'; import { Table, Form, Input } from 'antd';
import ScrollContainer from 'react-indiana-drag-scroll'; import ScrollContainer from 'react-indiana-drag-scroll';
import {
updateLaancAprv,
updateLaancAprvReview
} from '@src/redux/features/laanc/laancThunk';
export default function OperationCheckBoxModal(props) { export default function OperationCheckBoxModal(props) {
console.log('>>', props.checkData);
const scrollContainerRef = useRef(null); const scrollContainerRef = useRef(null);
const [dataSource, setDataSource] = useState(props.checkData); const [dataSource, setDataSource] = useState(
props.checkData.map((item, index) => ({
...item,
key: `parent_${item.planSno}_${index}`,
reviewedReason: item.reviewedReason || ''
}))
);
const [tempDataSource, setTempDataSource] = useState(
dataSource.map(item => {
return {
planAreaSno: item.planAreaSno,
reviewedReason: item.reviewedReason || '',
reqRadius: item.reqRadius || '',
fltElev: item.fltElev || '',
dtl: item.dtl || '',
era: item.era || '',
rm: item.rm || ''
};
})
); // 임시 데이터 소스 추가
const dispatch = useDispatch();
const EditableRow = ({ index, ...props }) => { const [form] = Form.useForm();
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<tr {...props} />
</Form>
);
};
const EditableCell = ({ const EditableCell = ({
title,
editable, editable,
children, children,
dataIndex, dataIndex,
@ -32,50 +48,34 @@ export default function OperationCheckBoxModal(props) {
handleSave, handleSave,
...restProps ...restProps
}) => { }) => {
const [editing, setEditing] = useState(false);
const inputRef = useRef(null);
const [form] = Form.useForm();
useEffect(() => {
if (editing) {
inputRef.current?.focus();
}
}, [editing]);
const toggleEdit = () => { const toggleEdit = () => {
setEditing(!editing); form.setFieldsValue({
form.setFieldsValue({ [dataIndex]: record[dataIndex] }); [dataIndex]: record[dataIndex]
});
}; };
const save = async () => { const save = async () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
setEditing(false);
handleSave({ ...record, ...values }); handleSave({ ...record, ...values });
} catch (errInfo) { } catch (errInfo) {}
console.log('Save failed:', errInfo);
}
}; };
let childNode = children; let childNode = children;
if (editable) { if (editable) {
childNode = editing ? ( childNode = (
<Form.Item <Form.Item
style={{ margin: 0 }} className='editable-input'
name={dataIndex} name={`${record.planAreaSno}`} // 고유한 이름 설정
rules={[{ required: true, message: `${title} is required.` }]} initialValue={record[dataIndex]}
> >
<Input ref={inputRef} onPressEnter={save} onBlur={save} /> <Input
onPressEnter={save}
onBlur={save}
placeholder='재검토 사유를 작성해주세요'
/>
</Form.Item> </Form.Item>
) : (
<div
className='editable-cell-value-wrap'
style={{ paddingRight: 24 }}
onClick={toggleEdit}
>
{children}
</div>
); );
} }
@ -83,13 +83,62 @@ export default function OperationCheckBoxModal(props) {
}; };
const handleSave = row => { const handleSave = row => {
const newData = [...dataSource]; const newData = [...tempDataSource];
const index = newData.findIndex(item => row.key === item.key); newData.map(item => {
const item = newData[index]; if (row.hasOwnProperty(item.planAreaSno)) {
newData.splice(index, 1, { ...item, ...row }); item.reviewedReason = row[item.planAreaSno];
setDataSource(newData); }
});
setTempDataSource(newData);
};
const components = {
body: {
cell: EditableCell
}
}; };
const handleConfirm = async () => {
if (tempDataSource.filter(item => !item.reviewedReason).length > 0) {
return props.handlerErrorModal(
'필수값 입력 오류',
'재검토 항목을 입력 해 주세요.',
false
);
}
const planAreaSnoList = tempDataSource.map(item => item.planAreaSno);
dispatch(updateLaancAprv(tempDataSource))
.then(updateRes => {
if (updateRes.meta.requestStatus === 'fulfilled') {
return dispatch(
updateLaancAprvReview({ planAreaSnoList, reviewedType: 'A' })
);
} else {
throw new Error('요청 처리에 실패했습니다.');
}
})
.then(() => {
props.handlerSearch(
props.filterId,
{
startDate: props.startDate,
endDate: props.endDate
},
props.filterArea
);
props.handlerErrorModal('성공', '재검토 요청이 완료되었습니다.', false);
props.setIsCheckBoxModal(false);
})
.catch(err => {
props.handlerErrorModal(
'실패',
'재검토 요청을 실패하였습니다. 다시 시도해주세요.',
true
);
});
};
const defaultColumns = [ const defaultColumns = [
{ {
title: ( title: (
@ -101,7 +150,7 @@ export default function OperationCheckBoxModal(props) {
), ),
dataIndex: 'applyNo', dataIndex: 'applyNo',
align: 'center', align: 'center',
width: '20px' width: '40px'
}, },
{ {
title: ( title: (
@ -231,7 +280,7 @@ export default function OperationCheckBoxModal(props) {
), ),
dataIndex: 'approvalCd', dataIndex: 'approvalCd',
align: 'center', align: 'center',
width: '10px', width: '50px',
render: approvalCd => { render: approvalCd => {
return ( return (
<> <>
@ -256,7 +305,7 @@ export default function OperationCheckBoxModal(props) {
), ),
dataIndex: 'reviewedType', dataIndex: 'reviewedType',
align: 'center', align: 'center',
width: '30px', width: '20px',
render: reviewedType => { render: reviewedType => {
return ( return (
<> <>
@ -283,7 +332,7 @@ export default function OperationCheckBoxModal(props) {
align: 'center', align: 'center',
editable: true, editable: true,
render: reviewedReason => { render: reviewedReason => {
return reviewedReason ?? '재검토 사유를 작성해주세요'; return reviewedReason ?? '-';
} }
} }
]; ];
@ -304,13 +353,6 @@ export default function OperationCheckBoxModal(props) {
}; };
}); });
const components = {
body: {
row: EditableRow,
cell: EditableCell
}
};
return ( return (
<Modal <Modal
isOpen={props.isCheckBoxModal} isOpen={props.isCheckBoxModal}
@ -331,42 +373,38 @@ export default function OperationCheckBoxModal(props) {
vertical={true} vertical={true}
horizontal={true} horizontal={true}
activationDistance={10} activationDistance={10}
ignoreElements='.editable-input' // 이 클래스의 요소는 드래그 이벤트에서 제외 ignoreElements='.editable-input'
> >
<div style={{ width: '2000px' }}> <div style={{ width: '2000px' }}>
<Table <Form form={form}>
dataSource={dataSource.map((item, index) => ({ <Table
...item, dataSource={dataSource}
key: `parent_${item.planSno}` components={components}
}))} columns={columns}
components={components} scroll={{ x: 1700 }}
rowClassName={record => { pagination={false}
let className = ''; rowHoverable={false}
if (record.approvalCd === 'S') { expandIconColumnIndex={-1}
className += 'flight-approval-row'; rowClassName={record => {
} else if (record.approvalCd === 'F') { let className = '';
className += 'flight-not-approval-row'; if (record.approvalCd === 'S') {
} else if (record.approvalCd === 'C') { className += 'flight-approval-row';
className += 'flight-condition-approval-row editable-row'; } else if (record.approvalCd === 'F') {
} else className += 'editable-row'; className += 'flight-not-approval-row';
} else if (record.approvalCd === 'C') {
className += 'flight-condition-approval-row editable-row';
} else className += 'editable-row';
return className; return className;
}} }}
columns={columns} />
scroll={{ x: 1700 }} </Form>
pagination={false}
rowHoverable={false}
expandIconColumnIndex={-1}
/>
</div> </div>
</ScrollContainer> </ScrollContainer>
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button <Button color='primary' onClick={handleConfirm}>
color='primary'
// onClick={() => props.setIsModal(!props.setIsModal)}
>
확인 확인
</Button> </Button>
</ModalFooter> </ModalFooter>

1
src/containers/flight/ControlApprovalsContainer.js

@ -736,6 +736,7 @@ export default function ControlApprovalsContainer({ mode }) {
startDate={startDate} startDate={startDate}
endDate={endDate} endDate={endDate}
selected={selected} selected={selected}
handlerSearch={handlerSearch}
handlerDetail={handlerDetail} handlerDetail={handlerDetail}
/> />
</div> </div>

4
src/containers/flight/OperationApprovalsContainer.js

@ -123,9 +123,7 @@ export default function OperationApprovalsContainer({ mode }) {
const features = map const features = map
.queryRenderedFeatures(e.point) .queryRenderedFeatures(e.point)
.find(feature => feature.source === 'operationLayer'); .find(feature => feature.source === 'operationLayer');
console.log(features);
if (features) { if (features) {
console.log(popupRef.current);
if (popupRef.current) { if (popupRef.current) {
popupRef.current.postMessage({ popupRef.current.postMessage({
type: 'matchingRow', type: 'matchingRow',
@ -167,7 +165,6 @@ export default function OperationApprovalsContainer({ mode }) {
if (e.data.type) { if (e.data.type) {
const { type } = e.data; const { type } = e.data;
const { payload } = e.data; const { payload } = e.data;
// console.log(payload);
switch (type) { switch (type) {
case 'search': case 'search':
const { search, searchDate, filterArea } = payload; const { search, searchDate, filterArea } = payload;
@ -889,6 +886,7 @@ export default function OperationApprovalsContainer({ mode }) {
endDate={endDate} endDate={endDate}
selected={selected} selected={selected}
selectedPlanSno={selectedPlanSno} selectedPlanSno={selectedPlanSno}
handlerSearch={handlerSearch}
handlerDetail={handlerDetail} handlerDetail={handlerDetail}
/> />
</div> </div>

Loading…
Cancel
Save