Browse Source

faq 컴포넌트 분할 작업

pull/2/head
김장현 11 months ago
parent
commit
aee2e65cfe
  1. 2
      .env.development
  2. 2
      .env.production
  3. 138
      src/components/cstmrService/faq/FaqForm.js
  4. 32
      src/components/cstmrService/faq/FaqSearchBox.js
  5. 62
      src/components/map/mapbox/MapBoxMap.js
  6. 172
      src/containers/cstmrService/faq/FaqContainer.js
  7. 293
      src/views/cstmrService/FaqView.js

2
.env.development

@ -4,7 +4,7 @@
# REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/ # REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/
REACT_APP_HOST = http://211.253.11.189:8080/ REACT_APP_HOST = http://211.253.11.189:8080/
REACT_APP_WS_HOST = ws://pav.palntour.com:8081/ws REACT_APP_WS_HOST = ws://211.253.11.189:8081/ws
REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/ REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/
# Naver Search API HOST # Naver Search API HOST

2
.env.production

@ -1,6 +1,6 @@
# REACT_APP_HOST = http://pav.palntour.com:8080/ # REACT_APP_HOST = http://pav.palntour.com:8080/
REACT_APP_HOST = http://211.253.11.189:8080/ REACT_APP_HOST = http://211.253.11.189:8080/
REACT_APP_WS_HOST = ws://pav.palntour.com:8081/ws REACT_APP_WS_HOST = ws://211.253.11.189:8081/ws
REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/ REACT_APP_IMAGE_HOST = https://palnet-file.s3.ap-northeast-2.amazonaws.com/
# Naver Search API HOST # Naver Search API HOST

138
src/components/cstmrService/faq/FaqForm.js

@ -0,0 +1,138 @@
import { useState } from 'react';
import {
Button,
Input,
Modal,
ModalHeader,
ModalBody,
ModalFooter,
Row,
Col,
FormGroup,
Label,
CustomInput
} from 'reactstrap';
import classnames from 'classnames';
export default function FaqForm({ isOpenFormModal, handlerOpenFormModal }) {
const [value, setValue] = useState('');
return (
<Modal
isOpen={isOpenFormModal}
toggle={handlerOpenFormModal}
className='modal-dialog-centered modal-lg faq-modal'
>
<ModalHeader toggle={handlerOpenFormModal}>질문 등록하기</ModalHeader>
<ModalBody>
<div>
<Row>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<Input type='select' size='sm'>
<option value=''>장치 신고</option>
<option value=''>사업 등록</option>
<option value=''>비행 승인</option>
<option value=''>항공 촬영</option>
<option value=''>기타</option>
</Input>
</FormGroup>
</Col>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>생성 사용자</Label>
<Input
type='text'
size='sm'
placeholder=''
value='홍길동'
disabled
/>
</FormGroup>
</Col>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>생성 일자</Label>
<Input
type='text'
size='sm'
placeholder=''
value='2023-10-15 00:00'
disabled
/>
</FormGroup>
</Col>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<div className='input-radio-inline'>
<CustomInput
type='radio'
id='exampleCustomRadio'
name='customRadio'
inline
label='표출'
defaultChecked
/>
<CustomInput
type='radio'
id='exampleCustomRadio2'
name='customRadio'
inline
label='미표출'
/>
</div>
</FormGroup>
</Col>
<Col className='list-input' md='12'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<Input type='text' size='sm' placeholder='' />
</FormGroup>
</Col>
<Col className='list-input' md='12'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<Input
className='faq-textarea'
type='textarea'
size='sm'
placeholder=''
onChange={e => setValue(e.target.value)}
/>
{/* 하단 필요없으면제거 */}
<span
className={classnames('textarea-counter-value float-right', {
'bg-danger': value.length > 300
})}
>
{`${value.length}/300`}
</span>
</FormGroup>
</Col>
</Row>
</div>
</ModalBody>
<ModalFooter>
<Button color='danger' onClick={handlerOpenFormModal}>
삭제
</Button>
<Button color='secondary' onClick={handlerOpenFormModal}>
취소
</Button>
<Button color='primary' onClick={handlerOpenFormModal}>
저장
</Button>
</ModalFooter>
</Modal>
);
}

32
src/components/cstmrService/faq/FaqSearchBox.js

@ -0,0 +1,32 @@
import { Input, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap';
import { Search } from 'react-feather';
export default function FaqSearchBox({ searchText, handlerSearchText }) {
return (
<InputGroup className='search-feather'>
<Input
type='text'
id='searchInput'
name='searchInput'
autoComplete='on'
placeholder='검색명을 입력하세요.'
value={searchText}
onChange={handlerSearchText}
onKeyPress={e => {
if (e.key === 'Enter') {
}
}}
/>
<InputGroupAddon
addonType='prepend'
onClick={() => {
console.log('???');
}}
>
<InputGroupText>
<Search size={14} />
</InputGroupText>
</InputGroupAddon>
</InputGroup>
);
}

62
src/components/map/mapbox/MapBoxMap.js

@ -216,6 +216,45 @@ const uamPosition = {
let gridCoords = []; let gridCoords = [];
let altitudeMarker = []; let altitudeMarker = [];
let linerAltitude = [
{
lng: 126.734619,
lat: 37.515349,
altitude: 120,
type: '0003'
},
{
lng: 126.852305,
lat: 37.601256,
altitude: 120,
type: '0003'
},
{
lng: 126.752454,
lat: 37.531588,
altitude: '45~100',
type: '0006'
},
{
lng: 126.83243,
lat: 37.585869,
altitude: '45~100',
type: '0006'
},
{
lng: 126.771088,
lat: 37.546521,
altitude: 0,
type: '0001'
},
{
lng: 126.811953,
lat: 37.569554,
altitude: 0,
type: '0001'
}
];
let linerAltitudeMarker = [];
export default function MapBoxMap() { export default function MapBoxMap() {
const naver = window.naver; const naver = window.naver;
@ -300,6 +339,9 @@ export default function MapBoxMap() {
}); });
gridCoords = []; gridCoords = [];
} }
if (linerAltitudeMarker.length > 0) {
linerAltitudeMarker.map(i => i.remove());
}
if (!mapControl.liner) { if (!mapControl.liner) {
if (gridCoords.length <= 0) { if (gridCoords.length <= 0) {
@ -353,6 +395,22 @@ export default function MapBoxMap() {
} }
}); });
} }
} else {
linerAltitude.map(i => {
if (mapControl[`area${i.type}`]) {
const el = document.createElement('div');
el.style.color = '#000000';
el.style.fontSize = '1rem';
el.innerText = i.altitude;
const marker = new mapboxgl.Marker({
element: el
})
.setLngLat([i.lng, i.lat])
.addTo(map);
marker.type = i.type;
linerAltitudeMarker.push(marker);
}
});
} }
let arrGeoJson = []; let arrGeoJson = [];
@ -437,6 +495,10 @@ export default function MapBoxMap() {
} }
)); ));
map.on('click', e => {
console.log(e);
});
map.on('style.load', () => { map.on('style.load', () => {
const layers = map.getStyle().layers; const layers = map.getStyle().layers;
const labelLayerId = layers.find( const labelLayerId = layers.find(

172
src/containers/cstmrService/faq/FaqContainer.js

@ -0,0 +1,172 @@
import { useCallback, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Button, Nav, NavItem, NavLink, TabContent, TabPane } from 'reactstrap';
import AppCollapse from '@components/app-collapse';
import FaqSearchBox from '../../../components/cstmrService/faq/FaqSearchBox';
import FaqForm from '../../../components/cstmrService/faq/FaqForm';
const data = [
{
title: (
<div className='faq-q'>
<h5>
<span className='faq-icon-q'>Q</span>
<span className='ti'>
<span>[장치신고]</span> ?
</span>
</h5>
<div>
<Button.Ripple color='flat-primary'>수정하기</Button.Ripple>
</div>
</div>
),
content: (
<div className='faq-a'>
<span className='faq-icon-a'>A</span>
<span className='faq-a-text'>
{/* br처리? 줄바꿈.. 추후에 생각 */}
그렇습니다.
<br />
<br />
- 사용용도가 영리 목적인 경우 : 무게에 상관없이 모두 신고
<br />
- 사용용도가 비영리 목적인 경우
<br />
· (무인멀티콥터, 무인비행기, 무인헬리콥터) 최대이륙중량 2kg 초과
신고
<br />
· (무인비행선) 연료의 무게를 제외한 자체무게가 12kg 초과, 길이 7m 초과
신고 <br />
</span>
</div>
)
},
{
title: (
<div className='faq-q'>
<h5>
<span className='faq-icon-q'>Q</span>
<span className='ti'>
<span>[비행승인]</span>
할까?
</span>
</h5>
<div>
<Button.Ripple color='flat-primary'>수정하기</Button.Ripple>
</div>
</div>
),
content: (
<div className='faq-a'>
<span className='faq-icon-a'>A</span>
<span className='faq-a-text'>
사방/천장이 막혀있는 밀폐된 실내 공간에서의 비행은 승인을 필요로 하지
않습니다. 또한, 적절한 조명장치가 있는 실내 공간이라면 야간에도 비행이
가능합니다. 다면 어떠한 경우에도 인명과 재산에 위험을 초래할 우려가
없도록 주의하여 비행하여야 합니다.
</span>
</div>
)
}
];
export default function FaqContainer() {
// ** States & Vars
const [activeTab, setActiveTab] = useState('1');
const { user } = useSelector(state => state.authState);
const [searchText, setSearchText] = useState('');
// ** Function to toggle tabs
const toggle = tab => setActiveTab(tab);
const [isOpenFormModal, setIsOpenFormModal] = useState(false);
const handlerSearchText = useCallback(
e => {
const { value } = e.target;
setSearchText(value);
},
[searchText]
);
const handlerOpenFormModal = () => {
setIsOpenFormModal(!isOpenFormModal);
};
return (
<div className='faq'>
{/* 검색바 */}
<div className='faq-search'>
<FaqSearchBox
searchText={searchText}
handlerSearchText={handlerSearchText}
/>
{user?.authId !== 'USER' && (
<Button
size='lg'
className='faq-admin-plus'
outline
color='primary'
onClick={() => setIsOpenFormModal(!isOpenFormModal)}
>
질문 등록하기
</Button>
)}
</div>
{/* 탭 컨텐츠 */}
<div>
<div className='tab-menu'>
<Nav pills>
<NavItem>
<NavLink active={activeTab === '1'} onClick={() => toggle('1')}>
<span className=''>전체</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '2'} onClick={() => toggle('2')}>
<span className=''>장치 신고</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '3'} onClick={() => toggle('3')}>
<span className=''>사업 등록</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '4'} onClick={() => toggle('4')}>
<span className=''>비행 승인</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '5'} onClick={() => toggle('5')}>
<span className=''>항공 촬영</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '6'} onClick={() => toggle('6')}>
<span className=''>기타</span>
</NavLink>
</NavItem>
</Nav>
</div>
<div>
<TabContent activeTab={activeTab}>
<TabPane tabId='1'>
<div>
<AppCollapse data={data} accordion type='margin' />
</div>
</TabPane>
<TabPane tabId='2'>장치신고</TabPane>
<TabPane tabId='3'>사업 등록</TabPane>
<TabPane tabId='4'>비행 승인</TabPane>
<TabPane tabId='5'>항공 촬영</TabPane>
<TabPane tabId='6'>기타</TabPane>
</TabContent>
</div>
</div>
<FaqForm
isOpenFormModal={isOpenFormModal}
handlerOpenFormModal={handlerOpenFormModal}
/>
</div>
);
}

293
src/views/cstmrService/FaqView.js

@ -1,300 +1,15 @@
import '../../assets/css/custom.css'; import '../../assets/css/custom.css';
import '@styles/react/libs/flatpickr/flatpickr.scss'; import '@styles/react/libs/flatpickr/flatpickr.scss';
import '@styles/react/libs/tables/react-dataTable-component.scss'; import '@styles/react/libs/tables/react-dataTable-component.scss';
import { useState, useEffect } from 'react'
import { useParams, Link } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
import { CustomMainLayout } from '../../components/layout/CustomMainLayout'; import { CustomMainLayout } from '../../components/layout/CustomMainLayout';
import { import FaqContainer from '../../containers/cstmrService/faq/FaqContainer';
Card,
CardBody,
CardText,
Button,
ButtonGroup,
Input,
InputGroup,
InputGroupAddon,
InputGroupText,
Modal,
ModalHeader,
ModalBody,
ModalFooter,
Nav,
NavItem,
NavLink,
TabContent,
TabPane,
Row,
Col,
FormGroup,
Label,
CustomInput
} from 'reactstrap';
import AppCollapse from '@components/app-collapse'
import Select from 'react-select'
import { selectThemeColors } from '@utils'
import classnames from 'classnames'
import { Search, HelpCircle, Info } from 'react-feather';
const data = [
{
title: (
<div className='faq-q'>
<h5>
<span className='faq-icon-q'>Q</span>
<span className='ti'><span>[장치신고]</span> ?</span>
</h5>
<div>
<Button.Ripple color='flat-primary'>수정하기</Button.Ripple>
</div>
</div>
),
content: (
<div className='faq-a'>
<span className='faq-icon-a'>A</span>
<span className='faq-a-text'>
{/* br처리? 줄바꿈.. 추후에 생각 */}
그렇습니다.<br/><br/>
- 사용용도가 영리 목적인 경우 : 무게에 상관없이 모두 신고<br/>
- 사용용도가 비영리 목적인 경우<br/>
· (무인멀티콥터, 무인비행기, 무인헬리콥터) 최대이륙중량 2kg 초과 신고<br/>
· (무인비행선) 연료의 무게를 제외한 자체무게가 12kg 초과, 길이 7m 초과 신고 <br/>
</span>
</div>
)
},
{
title: (
<div className='faq-q'>
<h5>
<span className='faq-icon-q'>Q</span>
<span className='ti'><span>[비행승인]</span> ?</span>
</h5>
<div>
<Button.Ripple color='flat-primary'>수정하기</Button.Ripple>
</div>
</div>
),
content: (
<div className='faq-a'>
<span className='faq-icon-a'>A</span>
<span className='faq-a-text'>
사방/천장이 막혀있는 밀폐된 실내 공간에서의 비행은 승인을 필요로 하지 않습니다.
또한, 적절한 조명장치가 있는 실내 공간이라면 야간에도 비행이 가능합니다. 다면 어떠한 경우에도 인명과 재산에 위험을 초래할 우려가 없도록 주의하여 비행하여야 합니다.
</span>
</div>
)
}
]
function FaqView() { function FaqView() {
// ** States & Vars return (
const [activeTab, setActiveTab] = useState('1'),
store = useSelector(state => state.users),
dispatch = useDispatch(),
{ id } = useParams()
// ** Function to toggle tabs
const toggle = tab => setActiveTab(tab)
const [centeredModal, setCenteredModal] = useState(false)
const [value, setValue] = useState('')
return <>
<CustomMainLayout title={'자주묻는 질문'}> <CustomMainLayout title={'자주묻는 질문'}>
<div className='faq'> <FaqContainer />
{/* 검색바 */}
<div className='faq-search'>
<InputGroup className='search-feather'>
<Input
type='text'
id='searchInput'
name='searchInput'
autoComplete='on'
placeholder='검색명을 입력하세요.'
/>
<InputGroupAddon addonType='prepend'>
<InputGroupText>
<Search size={14}/>
</InputGroupText>
</InputGroupAddon>
</InputGroup>
<Button size='lg' className='faq-admin-plus' outline color='primary' onClick={() => setCenteredModal(!centeredModal)}>질문 등록하기</Button>
<Modal isOpen={centeredModal} toggle={() => setCenteredModal(!centeredModal)} className='modal-dialog-centered modal-lg faq-modal'>
<ModalHeader toggle={() => setCenteredModal(!centeredModal)}>질문 등록하기</ModalHeader>
<ModalBody>
<div>
<Row>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<Input
type='select'
size='sm'
>
<option value=''>장치 신고</option>
<option value=''>사업 등록</option>
<option value=''>비행 승인</option>
<option value=''>항공 촬영</option>
<option value=''>기타</option>
</Input>
</FormGroup>
</Col>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>
생성 사용자
</Label>
<Input
type='text'
size='sm'
placeholder=''
value='홍길동'
disabled
/>
</FormGroup>
</Col>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>
생성 일자
</Label>
<Input
type='text'
size='sm'
placeholder=''
value='2023-10-15 00:00'
disabled
/>
</FormGroup>
</Col>
<Col className='list-input' md='3'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<div className='input-radio-inline'>
<CustomInput type='radio' id='exampleCustomRadio' name='customRadio' inline label='표출' defaultChecked />
<CustomInput type='radio' id='exampleCustomRadio2' name='customRadio' inline label='미표출' />
</div>
</FormGroup>
</Col>
<Col className='list-input' md='12'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<Input
type='text'
size='sm'
placeholder=''
/>
</FormGroup>
</Col>
<Col className='list-input' md='12'>
<FormGroup>
<Label for='test'>
<span className='necessary'>*</span>
</Label>
<Input
className='faq-textarea'
type='textarea'
size='sm'
placeholder=''
onChange={e => setValue(e.target.value)}
/>
{/* 하단 필요없으면제거 */}
<span
className={classnames('textarea-counter-value float-right', {
'bg-danger': value.length > 300
})}
>
{`${value.length}/300`}
</span>
</FormGroup>
</Col>
</Row>
</div>
</ModalBody>
<ModalFooter>
<Button color='danger' onClick={() => setCenteredModal(!centeredModal)}>
삭제
</Button>
<Button color='secondary' onClick={() => setCenteredModal(!centeredModal)}>
취소
</Button>
<Button color='primary' onClick={() => setCenteredModal(!centeredModal)}>
저장
</Button>
</ModalFooter>
</Modal>
</div>
{/* 탭 컨텐츠 */}
<div>
<div className='tab-menu'>
<Nav pills>
<NavItem>
<NavLink active={activeTab === '1'} onClick={() => toggle('1')}>
<span className=''>전체</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '2'} onClick={() => toggle('2')}>
<span className=''>장치 신고</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '3'} onClick={() => toggle('3')}>
<span className=''>사업 등록</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '4'} onClick={() => toggle('4')}>
<span className=''>비행 승인</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '5'} onClick={() => toggle('5')}>
<span className=''>항공 촬영</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '6'} onClick={() => toggle('6')}>
<span className=''>기타</span>
</NavLink>
</NavItem>
</Nav>
</div>
<div>
<TabContent activeTab={activeTab}>
<TabPane tabId='1'>
<div>
<AppCollapse data={data} accordion type='margin' />
</div>
</TabPane>
<TabPane tabId='2'>
장치신고
</TabPane>
<TabPane tabId='3'>
사업 등록
</TabPane>
<TabPane tabId='4'>
비행 승인
</TabPane>
<TabPane tabId='5'>
항공 촬영
</TabPane>
<TabPane tabId='6'>
기타
</TabPane>
</TabContent>
</div>
</div>
</div>
</CustomMainLayout> </CustomMainLayout>
</>; );
} }
export default FaqView; export default FaqView;

Loading…
Cancel
Save