Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
junh_eee(이준희) | 3269298ba3 | 8 months ago |
junh_eee(이준희) | 33cb319d96 | 8 months ago |
17 changed files with 1070 additions and 1891 deletions
@ -1,10 +1,3 @@
|
||||
import LayoutWrapper from '../layout/components/layout-wrapper'; |
||||
import Footer from '../layout/components/footer'; |
||||
|
||||
export default function Home() { |
||||
return ( |
||||
<LayoutWrapper layout='VerticalLayout' transition='fadeIn'> |
||||
<div>main</div> |
||||
</LayoutWrapper> |
||||
); |
||||
return <div>main</div>; |
||||
} |
||||
|
@ -0,0 +1,31 @@
|
||||
import { getDroneList } from '@/redux/features/basis/drone/droneThunk'; |
||||
import { useAppSelector } from '@/redux/hooks'; |
||||
import { AppDispatch } from '@/redux/store'; |
||||
import { useEffect } from 'react'; |
||||
import { useDispatch } from 'react-redux'; |
||||
|
||||
export default function Drone() { |
||||
const dispatch = useDispatch<AppDispatch>(); |
||||
const droneList = useAppSelector(state => state.drone.list); |
||||
|
||||
useEffect(() => { |
||||
console.log(droneList, '---list'); |
||||
}, [droneList]); |
||||
|
||||
const handler = () => { |
||||
dispatch( |
||||
getDroneList({ |
||||
groupId: 'C807F9', |
||||
page: 1 |
||||
}) |
||||
); |
||||
}; |
||||
return ( |
||||
<div> |
||||
main |
||||
<div style={{ background: '#ff00ff', width: '100px' }} onClick={handler}> |
||||
Redux-toolkit |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,11 @@
|
||||
'use client'; |
||||
|
||||
import Drone from './drone'; |
||||
|
||||
export default function Home() { |
||||
return ( |
||||
<> |
||||
<Drone /> |
||||
</> |
||||
); |
||||
} |
@ -1,26 +0,0 @@
|
||||
// ** Icons Import
|
||||
import { Heart } from 'react-feather'; |
||||
|
||||
function Footer() { |
||||
return ( |
||||
<p className='clearfix mb-0'> |
||||
<span className='float-md-left d-block d-md-inline-block mt-25'> |
||||
COPYRIGHT © {new Date().getFullYear()}{' '} |
||||
<a |
||||
href='https://1.envato.market/pixinvent_portfolio' |
||||
target='_blank' |
||||
rel='noopener noreferrer' |
||||
> |
||||
Pixinvent |
||||
</a> |
||||
<span className='d-none d-sm-inline-block'>, All rights Reserved</span> |
||||
</span> |
||||
<span className='float-md-right d-none d-md-block'> |
||||
Hand-crafted & Made with |
||||
<Heart size={14} /> |
||||
</span> |
||||
</p> |
||||
); |
||||
} |
||||
|
||||
export default Footer; |
@ -1,109 +0,0 @@
|
||||
// ** React Imports
|
||||
import { Fragment, useEffect, ReactNode } from 'react'; |
||||
|
||||
// ** Third Party Components
|
||||
import classnames from 'classnames'; |
||||
|
||||
// ** Store & Actions
|
||||
// import { useSelector, useDispatch } from 'react-redux'
|
||||
// import { handleContentWidth, handleMenuCollapsed, handleMenuHidden } from '@store/actions/layout'
|
||||
|
||||
// ** Styles
|
||||
import 'animate.css/animate.css'; |
||||
|
||||
interface Props { |
||||
children: ReactNode; |
||||
layout: string; |
||||
transition: string; |
||||
wrapperClass?: string; |
||||
appLayout?: string; |
||||
routeMeta?: { |
||||
authRoute: boolean; |
||||
naveLink: string; |
||||
}; |
||||
} |
||||
|
||||
function LayoutWrapper(props: Props) { |
||||
// ** Props
|
||||
const { |
||||
layout, |
||||
children, |
||||
appLayout = '', |
||||
wrapperClass = '', |
||||
transition, |
||||
routeMeta |
||||
} = props; |
||||
|
||||
// ** Store Vars
|
||||
// const dispatch = useDispatch()
|
||||
// const store = useSelector(state => state)
|
||||
// const navbarStore = store.navbar
|
||||
// const contentWidth = store.layout.contentWidth
|
||||
|
||||
//** Vars
|
||||
const Tag = layout === 'HorizontalLayout' && !appLayout ? 'div' : Fragment; |
||||
|
||||
// ** Clean Up Function
|
||||
// const cleanUp = () => {
|
||||
// if (routeMeta) {
|
||||
// if (routeMeta.contentWidth) {
|
||||
// dispatch(handleContentWidth('full'))
|
||||
// }
|
||||
// if (routeMeta.menuCollapsed) {
|
||||
// dispatch(handleMenuCollapsed(!routeMeta.menuCollapsed))
|
||||
// }
|
||||
// if (routeMeta.menuHidden) {
|
||||
// dispatch(handleMenuHidden(!routeMeta.menuHidden))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// ** ComponentDidMount
|
||||
// useEffect(() => {
|
||||
// if (routeMeta) {
|
||||
// if (routeMeta.contentWidth) {
|
||||
// dispatch(handleContentWidth(routeMeta.contentWidth))
|
||||
// }
|
||||
// if (routeMeta.menuCollapsed) {
|
||||
// dispatch(handleMenuCollapsed(routeMeta.menuCollapsed))
|
||||
// }
|
||||
// if (routeMeta.menuHidden) {
|
||||
// dispatch(handleMenuHidden(routeMeta.menuHidden))
|
||||
// }
|
||||
// }
|
||||
// return () => cleanUp()
|
||||
// }, [])
|
||||
|
||||
return ( |
||||
<div |
||||
className={classnames('app-content content overflow-hidden', { |
||||
[wrapperClass]: wrapperClass |
||||
// 'show-overlay': navbarStore.query.length
|
||||
})} |
||||
> |
||||
<div className='content-overlay'></div> |
||||
<div className='header-navbar-shadow' /> |
||||
<div |
||||
className={classnames({ |
||||
'content-wrapper': !appLayout, |
||||
'content-area-wrapper': appLayout, |
||||
// 'container p-0': contentWidth === 'boxed',
|
||||
[`animate__animated animate__${transition}`]: |
||||
transition !== 'none' && transition.length |
||||
})} |
||||
> |
||||
<Tag |
||||
/*eslint-disable */ |
||||
{...(layout === 'HorizontalLayout' && !appLayout |
||||
? { className: classnames({ 'content-body': !appLayout }) } |
||||
: {})} |
||||
/*eslint-enable */ |
||||
> |
||||
{children} |
||||
</Tag> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default LayoutWrapper; |
@ -0,0 +1,25 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'; |
||||
import { InitDroneState } from './droneState'; |
||||
import { getDroneList, getIdntfList } from './droneThunk'; |
||||
|
||||
const droneSlice = createSlice({ |
||||
name: 'droneSlice', |
||||
initialState: InitDroneState, |
||||
reducers: {}, |
||||
extraReducers: builder => { |
||||
builder.addCase(getDroneList.fulfilled, (state, action) => { |
||||
const { data, count } = action.payload; |
||||
state.list = data.items; |
||||
state.total = data.total; |
||||
state.count = count; |
||||
}); |
||||
builder.addCase(getIdntfList.fulfilled, (state, action) => { |
||||
const { data, count } = action.payload; |
||||
state.listIdntf = data; |
||||
state.idntfCount = count; |
||||
state.isRefreshIdntf = false; |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
export const droneReducer = droneSlice.reducer; |
@ -0,0 +1,71 @@
|
||||
export const InitDroneState = { |
||||
list: undefined, |
||||
count: 0, |
||||
detail: undefined, |
||||
searchParams: '', |
||||
selectData: undefined, |
||||
listIdntf: undefined, |
||||
idntfCount: 0, |
||||
isRefreshIdntf: false, |
||||
page: 1, |
||||
total: 0 |
||||
}; |
||||
|
||||
export interface DroneState { |
||||
list: DroneData[] | undefined; |
||||
count: number | 0; |
||||
detail: DroneData | undefined; |
||||
searchParams: string | ''; |
||||
selectData: SelectData | undefined; |
||||
listIdntf: IdntfData[] | undefined; |
||||
idntfCount: number | 0; |
||||
isRefreshIdntf: boolean | false; |
||||
page: number | 1; |
||||
total: number | 0; |
||||
} |
||||
|
||||
export interface SelectData { |
||||
groupId: string; |
||||
groupNm: string; |
||||
} |
||||
|
||||
export interface DroneData { |
||||
groupId: string; |
||||
arcrftSno: number; |
||||
arcrftHght: number; |
||||
arcrftLngth: number; |
||||
arcrftModelNm: string; |
||||
arcrftTypeCd: string; |
||||
arcrftWdth: number; |
||||
arcrftWght: number; |
||||
cameraYn: string; |
||||
createDt: Date; |
||||
createUserId: string; |
||||
insrncYn: string; |
||||
prdctCmpnNm: string; |
||||
prdctDate: Date; |
||||
prdctNum: string; |
||||
takeoffWght: number; |
||||
updateDt: Date; |
||||
updateUserId: string; |
||||
imageUrl: string; |
||||
wghtTypeCd: string; |
||||
idntfNum: string; |
||||
newIdntfNum: string; |
||||
idntfTypeCd: string; |
||||
ownerSno: number; |
||||
ownerNm: string; |
||||
hpno: string; |
||||
telno: string; |
||||
useYn: string; |
||||
file: FileList; |
||||
} |
||||
|
||||
export interface IdntfData { |
||||
idntfNum: string; |
||||
newIdntfNum: string; |
||||
isSave: boolean; |
||||
updateDt: Date; |
||||
createDt: Date; |
||||
cstmrSno: number; |
||||
} |
@ -0,0 +1,146 @@
|
||||
import axios from '../../../../utils/axiosInterceptor'; |
||||
import qs from 'qs'; |
||||
|
||||
import { createAsyncThunk } from '@reduxjs/toolkit'; |
||||
import { DroneData } from './droneState'; |
||||
|
||||
// 드론 목록 조회
|
||||
export const getDroneList = createAsyncThunk( |
||||
'basis/getDroneList', |
||||
async (data: any) => { |
||||
try { |
||||
const queryString = qs.stringify(data, { |
||||
addQueryPrefix: true, |
||||
arrayFormat: 'repeat' |
||||
}); |
||||
const res = await axios.get(`api/bas/dron/list${queryString}`); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 드론 상세 조회
|
||||
export const getDroneDetail = createAsyncThunk( |
||||
'basis/getDroneDetail', |
||||
async (id: number) => { |
||||
try { |
||||
const res = await axios.get(`api/bas/dron/detail/${id}`); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 드론 생성
|
||||
export const createDrone = createAsyncThunk( |
||||
'basis/createDrone', |
||||
async (data: DroneData) => { |
||||
try { |
||||
const res = await axios.post('api/bas/dron/create', data); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 드론 수정
|
||||
export const updateDrone = createAsyncThunk( |
||||
'basis/updateDrone', |
||||
async (data: DroneData) => { |
||||
try { |
||||
const res = await axios.put('api/bas/dron/update', data); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 드론 삭제
|
||||
export const deleteDrone = createAsyncThunk( |
||||
'basis/deleteDrone', |
||||
async (id: number) => { |
||||
try { |
||||
const res = await axios.delete(`api/bas/dron/delete/${id}`); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 식별장치 목록 조회
|
||||
export const getIdntfList = createAsyncThunk( |
||||
'basis/getIdntfList', |
||||
async (id: number) => { |
||||
try { |
||||
const res = await axios.get(`api/bas/dron/idntf/list/${id}`); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 식별장치 수정
|
||||
export const updateIdntf = createAsyncThunk( |
||||
'basis/updateIdntf', |
||||
async (item: { id: number; data: any[] }) => { |
||||
try { |
||||
const res = await axios.put(`/api/bas/dron/idntf/update/${item.id}`, { |
||||
idntfNum: item.data[0].idntfNum, |
||||
ownerNm: item.data[0].ownerNm, |
||||
hpno: item.data[0].hpno |
||||
}); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 식별장치 삭제
|
||||
export const deleteIdntf = createAsyncThunk( |
||||
'basis/deleteIdntf', |
||||
async (id: string) => { |
||||
try { |
||||
const res = await axios.delete(`api/bas/dron/idntf/delete/${id}`); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 식별장치 생성
|
||||
export const createIdntf = createAsyncThunk( |
||||
'basis/createIdntf', |
||||
async (item: { data: any[]; arcrftSno: number }) => { |
||||
try { |
||||
const res = await axios.post('api/bas/dron/idntf/create', item); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
||||
|
||||
// 파일 업로드
|
||||
export const fileUpload = createAsyncThunk( |
||||
'basis/fileUpload', |
||||
async (file: any) => { |
||||
try { |
||||
let form = new FormData(); |
||||
form.append('file', file); |
||||
|
||||
const res = await axios.post('api/file/upload', form); |
||||
return res.data; |
||||
} catch (error) { |
||||
console.error(error); |
||||
} |
||||
} |
||||
); |
@ -0,0 +1,7 @@
|
||||
import { AppDispatch, store } from './store'; |
||||
import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'; |
||||
|
||||
type RootState = ReturnType<typeof store.getState>; |
||||
|
||||
export const useAppDispatch = () => useDispatch<AppDispatch>(); |
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector; |
@ -0,0 +1,10 @@
|
||||
'use client'; |
||||
import { store } from './store'; |
||||
import { Provider } from 'react-redux'; |
||||
|
||||
type Props = { |
||||
children: React.ReactNode; |
||||
}; |
||||
export default function ReduxProvider({ children }: Props) { |
||||
return <Provider store={store}>{children}</Provider>; |
||||
} |
@ -0,0 +1,11 @@
|
||||
import { combineReducers } from '@reduxjs/toolkit'; |
||||
import { droneReducer } from './features/basis/drone/droneSlice'; |
||||
|
||||
const rootReducer = (state: any, action: any) => { |
||||
const combineReducer = combineReducers({ |
||||
drone: droneReducer |
||||
}); |
||||
|
||||
return combineReducer(state, action); |
||||
}; |
||||
export default rootReducer; |
@ -0,0 +1,9 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'; |
||||
import rootReducer from './rootReducer'; |
||||
|
||||
export const store = configureStore({ |
||||
reducer: rootReducer |
||||
}); |
||||
|
||||
export type RootState = ReturnType<typeof store.getState>; |
||||
export type AppDispatch = typeof store.dispatch; |
@ -0,0 +1,27 @@
|
||||
import axios, { AxiosInstance } from 'axios'; |
||||
import { getAccessToken } from './jwtToken'; |
||||
import { store } from '@/redux/store'; |
||||
|
||||
const axiosInstance: AxiosInstance = axios.create({ |
||||
baseURL: 'http://121.190.193.50:6081/' |
||||
}); |
||||
|
||||
axiosInstance.interceptors.request.use( |
||||
async config => { |
||||
config.headers['Authorization'] = |
||||
'palnet eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJwYWxuZXQiLCJjc3RtclNubyI6MiwiZXhwIjoxNzA4MzA2Nzg4LCJ1c2VySWQiOiJwYWxuZXQiLCJpYXQiOjE3MDY0OTIzODh9.X5S5oF5ZWcTK6FwjpVAfRwffuwLeCHUssn1OEJbsSFJDzi-Vp_DdnfgIvWAM1ry97VmNfFsT9bpX8XhE4dRnWg'; |
||||
// let accessToken = await getAccessToken();
|
||||
|
||||
// config.headers['Authorization'] = accessToken;
|
||||
// // alert(JSON.stringify(config.headers));
|
||||
// // store.dispatch({
|
||||
// // // type: GLOBAL_LOADING
|
||||
// // });
|
||||
return config; |
||||
}, |
||||
error => { |
||||
return Promise.reject(error); |
||||
} |
||||
); |
||||
|
||||
export default axiosInstance; |
@ -0,0 +1,20 @@
|
||||
import Cookies, { CookieAttributes, CookiesStatic } from 'js-cookie'; |
||||
|
||||
const CookieStorageBuilder = (cookies: CookiesStatic) => ({ |
||||
setCookie: (key: string, value: string, options?: CookieAttributes) => |
||||
cookies.set(key, value, { |
||||
path: '/', |
||||
secure: process.env.NODE_ENV === 'production' ? false : false, |
||||
sameSite: 'Lax', |
||||
...options |
||||
}), |
||||
getCookie: (key: string) => cookies.get(key), |
||||
removeCookie: (key: string) => cookies.remove(key) |
||||
}); |
||||
|
||||
export const cookieStorage = CookieStorageBuilder(Cookies); |
||||
|
||||
const COOKIE_BASE_NAME = 'palnet'; |
||||
|
||||
export const COOKIE_ACCESS_TOKEN = `${COOKIE_BASE_NAME}_accs`; |
||||
export const COOKIE_REFRESH_TOKEN = `${COOKIE_BASE_NAME}_rfrs`; |
@ -0,0 +1,51 @@
|
||||
import decode from 'jwt-decode'; |
||||
import { |
||||
cookieStorage, |
||||
COOKIE_ACCESS_TOKEN, |
||||
COOKIE_REFRESH_TOKEN |
||||
} from './cookie'; |
||||
|
||||
const JWT_FLEFIX = 'palnet '; |
||||
export const checkTokenExpired = (token?: string) => { |
||||
return true; |
||||
// const decodedToken = decode<LoginData>(token as string);
|
||||
|
||||
// if (parseInt(decodedToken.exp) < dayjs().unix()) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// return false;
|
||||
}; |
||||
|
||||
export const getAccessToken = async () => { |
||||
let token = cookieStorage.getCookie(COOKIE_ACCESS_TOKEN); |
||||
|
||||
if (!token || token == undefined || token == 'undefined') { |
||||
return ''; |
||||
} |
||||
|
||||
// if (checkTokenExpired(token)) {
|
||||
// //freshtoken 으로 재발급 진행.
|
||||
// const refreshToken = getRefreshToken();
|
||||
// //const isRefresh = store.getState()?.authState?.isRefresh;
|
||||
|
||||
// if (refreshToken) {
|
||||
// // if (!store.getState()?.authState?.isRefresh) {
|
||||
// const decodeToken = decode<LoginData>(token as string);
|
||||
// const cstmrSno: number = decodeToken.cstmrSno;
|
||||
|
||||
// const { data, errorCode } = await refreshTokenAPI(cstmrSno, refreshToken);
|
||||
// if (errorCode === '-101') {
|
||||
// cookieStorage.setCookie(COOKIE_REFRESH_TOKEN, '');
|
||||
// }
|
||||
// //REFHRESTH 토큰 넣기
|
||||
// cookieStorage.setCookie(COOKIE_ACCESS_TOKEN, data.accessToken);
|
||||
// cookieStorage.setCookie(COOKIE_REFRESH_TOKEN, data.refreshToken);
|
||||
// token = data.refreshToken;
|
||||
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
return JWT_FLEFIX + token; |
||||
}; |
Loading…
Reference in new issue