Browse Source

faq reducse saga 생성

pull/2/head
김장현 11 months ago
parent
commit
eea59ddca5
  1. 11
      src/components/cstmrService/faq/FaqSearchBox.js
  2. 96
      src/containers/cstmrService/faq/FaqContainer.js
  3. 21
      src/modules/cstmrService/faq/action/index.ts
  4. 13
      src/modules/cstmrService/faq/apis/index.ts
  5. 16
      src/modules/cstmrService/faq/model/index.ts
  6. 15
      src/modules/cstmrService/faq/reducers/index.ts
  7. 40
      src/modules/cstmrService/faq/sagas/index.ts
  8. 6
      src/redux/reducers/rootReducer.ts

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

@ -1,7 +1,11 @@
import { Input, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap';
import { Search } from 'react-feather';
export default function FaqSearchBox({ searchText, handlerSearchText }) {
export default function FaqSearchBox({
searchText,
handlerChangeSearchText,
handlerEnterSearchText
}) {
return (
<InputGroup className='search-feather'>
<Input
@ -11,16 +15,17 @@ export default function FaqSearchBox({ searchText, handlerSearchText }) {
autoComplete='on'
placeholder='검색명을 입력하세요.'
value={searchText}
onChange={handlerSearchText}
onChange={handlerChangeSearchText}
onKeyPress={e => {
if (e.key === 'Enter') {
handlerEnterSearchText();
}
}}
/>
<InputGroupAddon
addonType='prepend'
onClick={() => {
console.log('???');
handlerEnterSearchText();
}}
>
<InputGroupText>

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

@ -1,7 +1,8 @@
import { useCallback, useState } from 'react';
import { useCallback, useEffect, useLayoutEffect, 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 { LIST } from '../../../modules/cstmrService/faq/action';
import FaqSearchBox from '../../../components/cstmrService/faq/FaqSearchBox';
import FaqForm from '../../../components/cstmrService/faq/FaqForm';
@ -72,7 +73,7 @@ const data = [
export default function FaqContainer() {
// ** States & Vars
const [activeTab, setActiveTab] = useState('1');
const [activeTab, setActiveTab] = useState('전체');
const { user } = useSelector(state => state.authState);
const [searchText, setSearchText] = useState('');
@ -80,7 +81,23 @@ export default function FaqContainer() {
const toggle = tab => setActiveTab(tab);
const [isOpenFormModal, setIsOpenFormModal] = useState(false);
const handlerSearchText = useCallback(
const dispatch = useDispatch();
const { faqList } = useSelector(state => state.faqState);
useEffect(() => {
handlerGetFaqList();
}, [activeTab]);
const handlerGetFaqList = () => {
dispatch(
LIST.request({
category: activeTab,
word: searchText
})
);
};
const handlerChangeSearchText = useCallback(
e => {
const { value } = e.target;
setSearchText(value);
@ -88,17 +105,50 @@ export default function FaqContainer() {
[searchText]
);
const handlerEnterSearchText = () => {
handlerGetFaqList();
};
const handlerOpenFormModal = () => {
setIsOpenFormModal(!isOpenFormModal);
};
const handlerFaqList = () => {
if (faqList?.length <= 0 || !faqList) return [];
return faqList.map(i => {
return {
title: (
<div className='faq-q'>
<h5>
<span className='faq-icon-q'>Q</span>
<span className='ti'>
<span>[{i.category}]</span>
{i.title}
</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'>{i.content}</span>
</div>
)
};
});
};
return (
<div className='faq'>
{/* 검색바 */}
<div className='faq-search'>
<FaqSearchBox
searchText={searchText}
handlerSearchText={handlerSearchText}
handlerChangeSearchText={handlerChangeSearchText}
handlerEnterSearchText={handlerEnterSearchText}
/>
{user?.authId !== 'USER' && (
<Button
@ -117,32 +167,50 @@ export default function FaqContainer() {
<div className='tab-menu'>
<Nav pills>
<NavItem>
<NavLink active={activeTab === '1'} onClick={() => toggle('1')}>
<NavLink
active={activeTab === '전체'}
onClick={() => toggle('전체')}
>
<span className=''>전체</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '2'} onClick={() => toggle('2')}>
<NavLink
active={activeTab === '장치신고'}
onClick={() => toggle('장치신고')}
>
<span className=''>장치 신고</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '3'} onClick={() => toggle('3')}>
<NavLink
active={activeTab === '사업등록'}
onClick={() => toggle('사업등록')}
>
<span className=''>사업 등록</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '4'} onClick={() => toggle('4')}>
<NavLink
active={activeTab === '비행승인'}
onClick={() => toggle('비행승인')}
>
<span className=''>비행 승인</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '5'} onClick={() => toggle('5')}>
<NavLink
active={activeTab === '항공촬영'}
onClick={() => toggle('항공촬영')}
>
<span className=''>항공 촬영</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink active={activeTab === '6'} onClick={() => toggle('6')}>
<NavLink
active={activeTab === '기타'}
onClick={() => toggle('기타')}
>
<span className=''>기타</span>
</NavLink>
</NavItem>
@ -150,16 +218,16 @@ export default function FaqContainer() {
</div>
<div>
<TabContent activeTab={activeTab}>
<TabPane tabId='1'>
<TabPane tabId={activeTab}>
<div>
<AppCollapse data={data} accordion type='margin' />
<AppCollapse data={handlerFaqList()} accordion type='margin' />
</div>
</TabPane>
<TabPane tabId='2'>장치신고</TabPane>
{/* <TabPane tabId='2'></TabPane>
<TabPane tabId='3'>사업 등록</TabPane>
<TabPane tabId='4'>비행 승인</TabPane>
<TabPane tabId='5'>항공 촬영</TabPane>
<TabPane tabId='6'>기타</TabPane>
<TabPane tabId='6'>기타</TabPane> */}
</TabContent>
</div>
</div>

21
src/modules/cstmrService/faq/action/index.ts

@ -0,0 +1,21 @@
import { AxiosError } from 'axios';
import { createAsyncAction, ActionType, createAction } from 'typesafe-actions';
import { IFaqList } from '../model';
// 목록 조회
const LIST_REQUEST = 'cstmrService/faq/LIST_REQUEST';
const LIST_SUCCESS = 'cstmrService/faq/LIST_SUCCESS';
const LIST_FAILURE = 'cstmrService/faq/LIST_FAILURE';
export const LIST = createAsyncAction(LIST_REQUEST, LIST_SUCCESS, LIST_FAILURE)<
{ category: string; word: string },
IFaqList[],
AxiosError
>();
const actions = {
LIST
};
export type FaqAction = ActionType<typeof actions>;

13
src/modules/cstmrService/faq/apis/index.ts

@ -0,0 +1,13 @@
import axios from '../../../utils/customAxiosUtil';
import qs from 'qs';
export const faqAPI = {
list: async ({ category, word }) => {
const url =
category === '전체'
? `api/bas/cns/faq?word=${word}`
: `api/bas/cns/faq?category=${category}&word=${word}`;
return await axios.get(url);
}
};

16
src/modules/cstmrService/faq/model/index.ts

@ -0,0 +1,16 @@
export interface IFaqState {
faqList: IFaqList[];
}
export interface IFaqList {
faqSno: number;
category: string;
title: string;
content: string;
viewCnt: number;
expsrYn: string;
createUserId: string;
createDt: string;
updateUserId: string;
updateDt: string;
}

15
src/modules/cstmrService/faq/reducers/index.ts

@ -0,0 +1,15 @@
import { createReducer } from 'typesafe-actions';
import produce from 'immer';
import * as Actions from '../action';
import { IFaqState } from '../model';
export const faqReducer = createReducer<IFaqState, Actions.FaqAction>({
faqList: []
})
// 목록
.handleAction(Actions.LIST.success, (state, action) =>
produce(state, draft => {
const data = action.payload;
draft.faqList = data;
})
);

40
src/modules/cstmrService/faq/sagas/index.ts

@ -0,0 +1,40 @@
import { call, put, takeEvery } from '@redux-saga/core/effects';
import { ActionType } from 'typesafe-actions';
import {
DELETE_MESSAGE,
DUPLATE_MESSAGE,
ERROR_MESSAGE,
SAVE_MESSAGE
} from '../../../../configs/constants';
import * as MessageActions from '../../../comn/message/actions/comnMessageAction';
import * as Actions from '../action';
import * as Apis from '../apis';
function* listSaga(action: ActionType<typeof Actions.LIST.request>) {
try {
const payload = action.payload;
const res = yield call(Apis.faqAPI.list, payload);
const { data, count, errorCode } = res;
if (errorCode) {
// 오류메시지 호출
yield put(
MessageActions.IS_ERROR({
errorCode: errorCode,
errorMessage: '처리중 오류가 발생하였습니다',
isHistoryBack: false,
isRefresh: false
})
);
return;
}
yield put(Actions.LIST.success(data));
} catch (error) {
yield put(Actions.LIST.failure(error));
}
}
export function* faqSaga() {
yield takeEvery(Actions.LIST.request, listSaga);
}

6
src/redux/reducers/rootReducer.ts

@ -46,6 +46,8 @@ import { flightReducer } from '../../modules/basis/flight/reducers/basisFlightRe
import { flightSaga } from '../../modules/basis/flight/sagas/basisFlightSaga';
import { laancSaga } from '../../modules/laanc/sagas/laancSagas';
import laancReducer from '../../modules/laanc/reducers/laancReducers';
import { faqSaga } from '../../modules/cstmrService/faq/sagas';
import { faqReducer } from '../../modules/cstmrService/faq/reducers';
export interface StoreState {
controlGpState: ControlGpState;
@ -63,6 +65,7 @@ export function* saga() {
yield all([fork(flightSaga)]);
yield all([fork(findSaga)]);
yield all([fork(laancSaga)]);
yield all([fork(faqSaga)]);
}
const rootReducer = combineReducers({
@ -92,7 +95,8 @@ const rootReducer = combineReducers({
analysisSimulatorState: analysisSimulatorReducer,
ControlGpWeatherState: controlGpReducer,
flightState: flightReducer,
findState: findAccountReducer
findState: findAccountReducer,
faqState: faqReducer
});
export default rootReducer;

Loading…
Cancel
Save