sanguu516
1 month ago
3 changed files with 447 additions and 15 deletions
@ -0,0 +1,375 @@ |
|||||||
|
import { |
||||||
|
Button, |
||||||
|
Modal, |
||||||
|
ModalHeader, |
||||||
|
ModalBody, |
||||||
|
ModalFooter |
||||||
|
} from '@component/ui'; |
||||||
|
import React, { useEffect, useState, useRef } from 'react'; |
||||||
|
import { Table, Form, Input } from 'antd'; |
||||||
|
import ScrollContainer from 'react-indiana-drag-scroll'; |
||||||
|
|
||||||
|
export default function OperationCheckBoxModal(props) { |
||||||
|
console.log('>>', props.checkData); |
||||||
|
const scrollContainerRef = useRef(null); |
||||||
|
const [dataSource, setDataSource] = useState(props.checkData); |
||||||
|
|
||||||
|
const EditableRow = ({ index, ...props }) => { |
||||||
|
const [form] = Form.useForm(); |
||||||
|
return ( |
||||||
|
<Form form={form} component={false}> |
||||||
|
<tr {...props} /> |
||||||
|
</Form> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
const EditableCell = ({ |
||||||
|
title, |
||||||
|
editable, |
||||||
|
children, |
||||||
|
dataIndex, |
||||||
|
record, |
||||||
|
handleSave, |
||||||
|
...restProps |
||||||
|
}) => { |
||||||
|
const [editing, setEditing] = useState(false); |
||||||
|
const inputRef = useRef(null); |
||||||
|
const [form] = Form.useForm(); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (editing) { |
||||||
|
inputRef.current?.focus(); |
||||||
|
} |
||||||
|
}, [editing]); |
||||||
|
|
||||||
|
const toggleEdit = () => { |
||||||
|
setEditing(!editing); |
||||||
|
form.setFieldsValue({ [dataIndex]: record[dataIndex] }); |
||||||
|
}; |
||||||
|
|
||||||
|
const save = async () => { |
||||||
|
try { |
||||||
|
const values = await form.validateFields(); |
||||||
|
setEditing(false); |
||||||
|
handleSave({ ...record, ...values }); |
||||||
|
} catch (errInfo) { |
||||||
|
console.log('Save failed:', errInfo); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
let childNode = children; |
||||||
|
|
||||||
|
if (editable) { |
||||||
|
childNode = editing ? ( |
||||||
|
<Form.Item |
||||||
|
style={{ margin: 0 }} |
||||||
|
name={dataIndex} |
||||||
|
rules={[{ required: true, message: `${title} is required.` }]} |
||||||
|
> |
||||||
|
<Input ref={inputRef} onPressEnter={save} onBlur={save} /> |
||||||
|
</Form.Item> |
||||||
|
) : ( |
||||||
|
<div |
||||||
|
className='editable-cell-value-wrap' |
||||||
|
style={{ paddingRight: 24 }} |
||||||
|
onClick={toggleEdit} |
||||||
|
> |
||||||
|
{children} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
return <td {...restProps}>{childNode}</td>; |
||||||
|
}; |
||||||
|
|
||||||
|
const handleSave = row => { |
||||||
|
const newData = [...dataSource]; |
||||||
|
const index = newData.findIndex(item => row.key === item.key); |
||||||
|
const item = newData[index]; |
||||||
|
newData.splice(index, 1, { ...item, ...row }); |
||||||
|
setDataSource(newData); |
||||||
|
}; |
||||||
|
|
||||||
|
const defaultColumns = [ |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
신청 |
||||||
|
<br /> |
||||||
|
번호 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'applyNo', |
||||||
|
align: 'center', |
||||||
|
width: '20px' |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
신청 <br /> |
||||||
|
구역 수 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'zoneNo', |
||||||
|
align: 'center', |
||||||
|
width: '20px' |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
행정 <br /> |
||||||
|
구역 1 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'addr1', |
||||||
|
width: '40px', |
||||||
|
align: 'center', |
||||||
|
render: addr1 => { |
||||||
|
return addr1 ?? '-'; |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
행정 <br /> |
||||||
|
구역 2 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'addr2', |
||||||
|
width: '40px', |
||||||
|
align: 'center', |
||||||
|
render: addr2 => { |
||||||
|
return addr2 ?? '-'; |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
상세 |
||||||
|
<br /> |
||||||
|
주소 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'addr3', |
||||||
|
width: '40px', |
||||||
|
align: 'center', |
||||||
|
render: addr3 => { |
||||||
|
return addr3 ?? '-'; |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
장애물 |
||||||
|
<br /> |
||||||
|
제한 표면 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'limitZoneNm', |
||||||
|
width: '10px', |
||||||
|
align: 'center' |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
중심 좌표 |
||||||
|
<br /> |
||||||
|
(위도, 경도) |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'areaList', |
||||||
|
align: 'center', |
||||||
|
width: '40px', |
||||||
|
render: (areaList, record) => ( |
||||||
|
<> |
||||||
|
{record.lat.toFixed(5)}, |
||||||
|
<br /> |
||||||
|
{record.lon.toFixed(5)} |
||||||
|
</> |
||||||
|
) |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
비행 반경 |
||||||
|
<br /> |
||||||
|
(m이내) |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'bufferZone', |
||||||
|
align: 'center', |
||||||
|
width: '30px' |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
신청 고도 |
||||||
|
<br /> |
||||||
|
(m이하) |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'fltElev', |
||||||
|
align: 'center', |
||||||
|
width: '30px' |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: <>비행 목적</>, |
||||||
|
dataIndex: 'purpose', |
||||||
|
align: 'center', |
||||||
|
width: '10px', |
||||||
|
render: purpose => { |
||||||
|
return purpose ?? '-'; |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
LAANC |
||||||
|
<br /> |
||||||
|
검토 결과 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'approvalCd', |
||||||
|
align: 'center', |
||||||
|
width: '10px', |
||||||
|
render: approvalCd => { |
||||||
|
return ( |
||||||
|
<> |
||||||
|
{approvalCd === 'U' |
||||||
|
? '비대상' |
||||||
|
: approvalCd === 'S' |
||||||
|
? '승인' |
||||||
|
: approvalCd === 'C' |
||||||
|
? '조건부승인' |
||||||
|
: '미승인'} |
||||||
|
</> |
||||||
|
); |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
관제과 |
||||||
|
<br /> |
||||||
|
검토결과 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'reviewedType', |
||||||
|
align: 'center', |
||||||
|
width: '30px', |
||||||
|
render: reviewedType => { |
||||||
|
return ( |
||||||
|
<> |
||||||
|
{reviewedType === 'R' |
||||||
|
? '검토완료' |
||||||
|
: reviewedType === 'W' |
||||||
|
? '검토대기' |
||||||
|
: reviewedType === 'C' |
||||||
|
? '검토취소' |
||||||
|
: '재검토요청'} |
||||||
|
</> |
||||||
|
); |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: ( |
||||||
|
<> |
||||||
|
재검토 <br /> |
||||||
|
사유 |
||||||
|
</> |
||||||
|
), |
||||||
|
dataIndex: 'reviewedReason', |
||||||
|
width: '110px', |
||||||
|
align: 'center', |
||||||
|
editable: true, |
||||||
|
render: reviewedReason => { |
||||||
|
return reviewedReason ?? '재검토 사유를 작성해주세요'; |
||||||
|
} |
||||||
|
} |
||||||
|
]; |
||||||
|
|
||||||
|
const columns = defaultColumns.map(col => { |
||||||
|
if (!col.editable) { |
||||||
|
return col; |
||||||
|
} |
||||||
|
return { |
||||||
|
...col, |
||||||
|
onCell: record => ({ |
||||||
|
record, |
||||||
|
editable: col.editable, |
||||||
|
dataIndex: col.dataIndex, |
||||||
|
title: col.title, |
||||||
|
handleSave |
||||||
|
}) |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
const components = { |
||||||
|
body: { |
||||||
|
row: EditableRow, |
||||||
|
cell: EditableCell |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<Modal |
||||||
|
isOpen={props.isCheckBoxModal} |
||||||
|
toggle={() => props.setIsCheckBoxModal(!props.setIsCheckBoxModal)} |
||||||
|
className='modal-dialog-centered modal-xl' |
||||||
|
> |
||||||
|
<ModalHeader |
||||||
|
toggle={() => props.setIsCheckBoxModal(!props.setIsCheckBoxModal)} |
||||||
|
> |
||||||
|
재검토 요청 |
||||||
|
</ModalHeader> |
||||||
|
<ModalBody className='onestop-validation'> |
||||||
|
<div className='invoice-list-dataTable flight-approval'> |
||||||
|
<ScrollContainer |
||||||
|
className='scroll-container' |
||||||
|
ref={scrollContainerRef} |
||||||
|
hideScrollbars={false} |
||||||
|
vertical={true} |
||||||
|
horizontal={true} |
||||||
|
activationDistance={10} |
||||||
|
ignoreElements='.editable-input' // 이 클래스의 요소는 드래그 이벤트에서 제외
|
||||||
|
> |
||||||
|
<div style={{ width: '2000px' }}> |
||||||
|
<Table |
||||||
|
dataSource={dataSource.map((item, index) => ({ |
||||||
|
...item, |
||||||
|
key: `parent_${item.planSno}` |
||||||
|
}))} |
||||||
|
components={components} |
||||||
|
rowClassName={record => { |
||||||
|
let className = ''; |
||||||
|
if (record.approvalCd === 'S') { |
||||||
|
className += 'flight-approval-row'; |
||||||
|
} else if (record.approvalCd === 'F') { |
||||||
|
className += 'flight-not-approval-row'; |
||||||
|
} else if (record.approvalCd === 'C') { |
||||||
|
className += 'flight-condition-approval-row editable-row'; |
||||||
|
} else className += 'editable-row'; |
||||||
|
|
||||||
|
return className; |
||||||
|
}} |
||||||
|
columns={columns} |
||||||
|
scroll={{ x: 1700 }} |
||||||
|
pagination={false} |
||||||
|
rowHoverable={false} |
||||||
|
expandIconColumnIndex={-1} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</ScrollContainer> |
||||||
|
</div> |
||||||
|
</ModalBody> |
||||||
|
<ModalFooter> |
||||||
|
<Button |
||||||
|
color='primary' |
||||||
|
// onClick={() => props.setIsModal(!props.setIsModal)}
|
||||||
|
> |
||||||
|
확인 |
||||||
|
</Button> |
||||||
|
</ModalFooter> |
||||||
|
</Modal> |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue