frontend add

This commit is contained in:
shinmj
2021-10-21 09:03:17 +09:00
parent 8caa4bbc5a
commit cb9d50511e
443 changed files with 88282 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
import { Page } from '@utils'
/**
* request payload
*/
export interface AttachmentPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
id?: string
isDelete?: boolean
}
const ATTACHMENT_API = '/portal-service/api/v1/attachments'
/**
* 첨부파일 관리 서비스
*/
export const attachmentService = {
url: ATTACHMENT_API,
search: ({ keywordType, keyword, size, page }: SearchPayload) => {
return useSWR<Page, AxiosError>(
[`${ATTACHMENT_API}?size=${size}&page=${page}`, keywordType, keyword],
(url, keywordType, keyword) =>
common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
delete: async ({ id, callback, errorCallback }: AttachmentPayload) => {
try {
const result = await axios.delete(`${ATTACHMENT_API}/${id}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
updateToggle: async ({
callback,
errorCallback,
id,
isDelete,
}: AttachmentPayload) => {
try {
const result = await axios.put(`${ATTACHMENT_API}/${id}/${isDelete}`, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,94 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface AuthorizationSavePayload {
authorizationName: string
urlPatternValue: string
httpMethodCode: string
sortSeq: number
}
/**
* request payload
*/
export interface AuthorizationPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
authorizationNo?: string
data?: AuthorizationSavePayload
}
/**
* 사용자 서비스 인가 API URL
*/
const AUTHORIZATION_URL = '/user-service/api/v1/authorizations'
/**
* 이용약관 관리 서비스
*/
export const authorizationService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${AUTHORIZATION_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (authorizationNo: string) =>
axios.get(`${AUTHORIZATION_URL}/${authorizationNo}`),
getNextSortSeq: async () => axios.get(`${AUTHORIZATION_URL}/sort-seq/next`),
delete: async ({
authorizationNo,
callback,
errorCallback,
}: AuthorizationPayload) => {
try {
const result = await axios.delete(
`${AUTHORIZATION_URL}/${authorizationNo}`,
)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: AuthorizationPayload) => {
try {
const result = await axios.post(AUTHORIZATION_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({
callback,
errorCallback,
authorizationNo,
data,
}: AuthorizationPayload) => {
try {
const result = await axios.put(
`${AUTHORIZATION_URL}/${authorizationNo}`,
data,
{
headers: common.headers,
},
)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,100 @@
import { ISite } from '@service'
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface BannerSavePayload {
siteId: number
bannerTypeCode: string
bannerTitle: string
attachmentCode: string
urlAddr: string
newWindowAt: boolean
bannerContent: string
sortSeq: number
}
/**
* request payload너
*/
export interface BannerPayload {
callback?: () => any
errorCallback?: (error: AxiosError) => void
bannerNo?: string
data?: BannerSavePayload
useAt?: boolean
}
/**
* 포털 서비스 배너 API URL
*/
const BANNER_URL = '/portal-service/api/v1/banners'
interface BannerSearchPayload extends SearchPayload {
siteId: string | number
}
/**
* 배너 관리 서비스
*/
export const bannerService = {
search: ({ keywordType, keyword, size, page, siteId }: BannerSearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${BANNER_URL}?size=${size}&page=${page}`, keywordType, keyword, siteId],
url => common.fetcher(url, { keywordType, keyword, siteId }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (bannerNo: string) => axios.get(`${BANNER_URL}/${bannerNo}`),
getNextSortSeq: async (siteId: number) =>
axios.get(`${BANNER_URL}/${siteId}/sort-seq/next`),
delete: async ({ bannerNo, callback, errorCallback }: BannerPayload) => {
try {
const result = await axios.delete(`${BANNER_URL}/${bannerNo}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: ({ data }: BannerPayload) =>
axios.post(BANNER_URL, data, {
headers: common.headers,
}),
update: ({ bannerNo, data }: BannerPayload) =>
axios.put(`${BANNER_URL}/${bannerNo}`, data, {
headers: common.headers,
}),
updateUseAt: async ({
callback,
errorCallback,
bannerNo,
useAt,
}: BannerPayload) => {
try {
const result = await axios.put(`${BANNER_URL}/${bannerNo}/${useAt}`, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
getSites: () => {
return new Promise<ISite[]>(async (resolve, rejects) => {
try {
const result = await axios.get(`/portal-service/api/v1/sites`)
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
}

View File

@@ -0,0 +1,112 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 게시판 타입
*/
export interface IBoardProps {
boardNo: number
boardName: string
skinTypeCode: string
titleDisplayLength: number
postDisplayCount: number
pageDisplayCount: number
newDisplayDayCount: number
editorUseAt: boolean
userWriteAt: boolean
commentUseAt: boolean
uploadUseAt: boolean
uploadLimitCount: number
uploadLimitSize: number
}
/**
* 저장 시 데이터 타입
*/
export interface BoardSavePayload {
boardNo?: number
boardName: string
skinTypeCode: string
titleDisplayLength: number
postDisplayCount: number
pageDisplayCount: number
newDisplayDayCount: number
editorUseAt: boolean
userWriteAt: boolean
commentUseAt: boolean
uploadUseAt: boolean
uploadLimitCount: number
uploadLimitSize: number
}
/**
* request payload
*/
export interface BoardPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
boardNo?: number
data?: BoardSavePayload
}
/**
* 게시판 스킨 유형
*/
export const SKINT_TYPE_CODE_NORMAL = 'normal'
export const SKINT_TYPE_CODE_FAQ = 'faq'
export const SKINT_TYPE_CODE_QNA = 'qna'
/**
* 포털 서비스 게시판 API URL
*/
const BOARD_URL = '/board-service/api/v1/boards'
/**
* 게시판 관리 서비스
*/
export const boardService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${BOARD_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (boardNo: number) => axios.get(`${BOARD_URL}/${boardNo}`),
delete: async ({ boardNo, callback, errorCallback }: BoardPayload) => {
try {
const result = await axios.delete(`${BOARD_URL}/${boardNo}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: BoardPayload) => {
try {
const result = await axios.post(BOARD_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({ callback, errorCallback, boardNo, data }: BoardPayload) => {
try {
const result = await axios.put(`${BOARD_URL}/${boardNo}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,207 @@
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
import { Page } from '@utils'
/**
* 코드 인터페이스
*/
export interface ICode {
// parentCodeId?: string
codeId: string
codeName: string
sortSeq: number
}
/**
* 상세코드 조회조건 인터페이스
*/
export interface ICodeDetailSearch extends SearchPayload {
parentCodeId?: string
}
/**
* 저장 시 데이터 타입
*/
export interface CodeSavePayload {
parentCodeId?: string
codeId: string
codeName: string
codeDescription: string
sortSeq: number
useAt: boolean
}
/**
* request payload
*/
export interface CodePayload {
callback: () => any
errorCallback: (error: AxiosError) => void
id?: string
data?: CodeSavePayload
useAt?: boolean
}
/**
* 코드 API URL
*/
const CODE_URL = '/portal-service/api/v1/codes'
const CODE_DETAIL_URL = '/portal-service/api/v1/code-details'
/**
* 코드 서비스
*/
export const codeService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) => {
return useSWR<Page, AxiosError>(
[`${CODE_URL}?size=${size}&page=${page}`, keywordType, keyword],
(url, keywordType, keyword) =>
common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
searchDetail: ({
parentCodeId,
keywordType,
keyword,
size,
page,
}: ICodeDetailSearch) => {
return useSWR<Page, AxiosError>(
[
`${CODE_DETAIL_URL}?size=${size}&page=${page}`,
parentCodeId === '-' ? '' : parentCodeId,
keywordType,
keyword,
],
(url, parentCodeId, keywordType, keyword) =>
common.fetcher(url, { parentCodeId, keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
getOne: (id: string) => {
return axios.get(`${CODE_URL}/${id}`, {
headers: common.headers,
})
},
getOneDetail: (id: string) => {
return axios.get(`${CODE_DETAIL_URL}/${id}`, {
headers: common.headers,
})
},
getParentCode: (id: string) => {
return axios.get(`${CODE_DETAIL_URL}/${id}/parent`, {
headers: common.headers,
})
},
delete: async ({ id, callback, errorCallback }: CodePayload) => {
try {
const result = await axios.delete(`${CODE_URL}/${id}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
deleteDetail: async ({ id, callback, errorCallback }: CodePayload) => {
try {
const result = await axios.delete(`${CODE_DETAIL_URL}/${id}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: CodePayload) => {
try {
const result = await axios.post(`${CODE_URL}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
saveDetail: async ({ callback, errorCallback, data }: CodePayload) => {
try {
const result = await axios.post(`${CODE_DETAIL_URL}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({ callback, errorCallback, id, data }: CodePayload) => {
try {
const result = await axios.put(`${CODE_URL}/${id}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
updateDetail: async ({ callback, errorCallback, id, data }: CodePayload) => {
try {
const result = await axios.put(`${CODE_DETAIL_URL}/${id}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
updateUse: async ({ callback, errorCallback, id, useAt }: CodePayload) => {
try {
const result = await axios.put(
`${CODE_URL}/${id}/toggle-use?useAt=${useAt}`,
{
headers: common.headers,
},
)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
updateUseDetail: async ({
callback,
errorCallback,
id,
useAt,
}: CodePayload) => {
try {
const result = await axios.put(
`${CODE_DETAIL_URL}/${id}/toggle-use?useAt=${useAt}`,
{
headers: common.headers,
},
)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
getCodeDetailList: async (parentCodeId: string) =>
axios.get(`${CODE_DETAIL_URL}/${parentCodeId}/codes`),
getParentCodeList: async () =>
axios.get(`${CODE_URL}-parent`, {
headers: common.headers,
}),
}

View File

@@ -0,0 +1,157 @@
import axios, { AxiosError } from 'axios'
import { Page, Pageable, Sort } from '@utils'
import { common } from './common'
export interface CommentPage {
empty: boolean
first: boolean
last: boolean
number: number
numberOfElements: number
pageable: Pageable
size: number
sort: Sort
totalElements: number
groupElements: number
totalPages: number
content: any[] | []
}
export interface IComment {
boardNo: number
postsNo: number
commentNo?: number
commentContent: string
groupNo?: number
parentCommentNo?: number
depthSeq: number
sortSeq?: number
deleteAt?: number
createdBy?: string
createdName?: string
createdDate?: string
mode?: 'none' | 'edit' | 'reply'
}
/**
* 저장 시 데이터 타입
*/
export interface CommentSavePayload {
boardNo: number
postsNo: number
commentNo?: number
commentContent: string
groupNo?: number
parentCommentNo?: number
depthSeq: number
sortSeq?: number
deleteAt?: number
createdBy?: string
createdName?: string
createdDate?: string
}
/**
* 삭제 시 데이터 타입
*/
export interface CommentDeletePayload {
boardNo: number
postsNo: number
}
/**
* request payload
*/
export interface CommentPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
boardNo?: number
postsNo?: number
commentNo?: number
data?: CommentSavePayload
}
/**
* 포털 서비스 게시물 API URL
*/
const COMMENT_URL = '/board-service/api/v1/comments'
/**
* 게시물 관리 서비스
*/
export const commentService = {
/* list: (boardNo: number, postsNo: number, size: number, page: number) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${COMMENT_URL}/${boardNo}/${postsNo}?size=${size}&page=${page}`],
url => common.fetcher(url, {}),
{ revalidateOnFocus: false, errorRetryCount: 0 },
), */
list: (boardNo: number, postsNo: number, size: number, page: number) =>
new Promise<CommentPage>((resolve, rejects) => {
try {
axios
.get(`${COMMENT_URL}/${boardNo}/${postsNo}?size=${size}&page=${page}`)
.then(result => {
resolve(result.data)
})
} catch (error) {
rejects(error)
}
}),
all: (boardNo: number, postsNo: number) =>
new Promise<Page>((resolve, rejects) => {
try {
axios.get(`${COMMENT_URL}/${boardNo}/${postsNo}/all`).then(result => {
resolve(result.data)
})
} catch (error) {
rejects(error)
}
}),
save: async ({ callback, errorCallback, data }: CommentPayload) => {
try {
const result = await axios.post(`${COMMENT_URL}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({ callback, errorCallback, data }: CommentPayload) => {
try {
const result = await axios.put(`${COMMENT_URL}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
delete: async ({
boardNo,
postsNo,
commentNo,
callback,
errorCallback,
}: CommentPayload) => {
try {
const result = await axios.delete(
`${COMMENT_URL}/${boardNo}/${postsNo}/${commentNo}`,
{
headers: common.headers,
},
)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,81 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface ContentSavePayload {
contentName: string
contentRemark: string
contentValue: string
}
/**
* request payload
*/
export interface ContentPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
contentNo?: string
data?: ContentSavePayload
}
/**
* 포털 서비스 컨텐츠 API URL
*/
const CONTENT_URL = '/portal-service/api/v1/contents'
/**
* 컨텐츠 관리 서비스
*/
export const contentService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${CONTENT_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (contentNo: string) => axios.get(`${CONTENT_URL}/${contentNo}`),
delete: async ({ contentNo, callback, errorCallback }: ContentPayload) => {
try {
const result = await axios.delete(`${CONTENT_URL}/${contentNo}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: ContentPayload) => {
try {
const result = await axios.post(CONTENT_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({
callback,
errorCallback,
contentNo,
data,
}: ContentPayload) => {
try {
const result = await axios.put(`${CONTENT_URL}/${contentNo}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,108 @@
import axios from 'axios'
export interface IFile {
key: string
file: File
}
export interface UploadInfoReqeust {
entityName?: string
entityId?: string
}
export interface IAttachmentResponse {
code: string
seq: number
id: string
originalFileName: string
physicalFileName: string
size: number
fileType: string
isDelete: boolean
createDate: Date
downloadCnt: number
entityId: string
entityName: string
}
export interface AttachmentSavePayload {
uniqueId: string
isDelete: boolean
}
export type UploadPayload = {
fileList?: IFile[]
attachmentCode?: string
info?: UploadInfoReqeust
list?: AttachmentSavePayload[]
}
const UPLOAD_API = '/portal-service/api/v1/attachments'
const DOWNLOAD_API = `/server/portal-service/api/v1/download`
let fileHeader = {
'Content-Type': 'multipart/form-data',
}
/**
* 파일 업로드 서비스
*/
export const fileService = {
url: UPLOAD_API,
downloadUrl: DOWNLOAD_API,
upload: async ({ fileList, attachmentCode, info, list }: UploadPayload) => {
let formData = new FormData()
fileList.map(item => {
formData.append('files', item.file)
})
if (info) {
formData.append(
'info',
new Blob([JSON.stringify(info)], { type: 'application/json' }),
)
}
if (list) {
formData.append(
'list',
new Blob([JSON.stringify(list)], { type: 'application/json' }),
)
}
// attachmentCode가 있는 경우 update라고 본다
if (attachmentCode) {
return axios.put(`${UPLOAD_API}/upload/${attachmentCode}`, formData, {
headers: fileHeader,
})
}
// attachmentCode가 없는 경우 신규 저장
return axios.post(`${UPLOAD_API}/upload`, formData, {
headers: fileHeader,
})
},
save: async ({ attachmentCode, info, list }: UploadPayload) => {
let formData = new FormData()
formData.append(
'info',
new Blob([JSON.stringify(info)], { type: 'application/json' }),
)
formData.append(
'list',
new Blob([JSON.stringify(list)], { type: 'application/json' }),
)
return axios.put(`${UPLOAD_API}/${attachmentCode}`, formData, {
headers: fileHeader,
})
},
getAttachmentList: (attachmentCode: string) => {
return axios.get(`${UPLOAD_API}/${attachmentCode}`)
},
deleteAll: (attachmentCode: string) =>
axios.delete(`${UPLOAD_API}/${attachmentCode}/children`),
}

View File

@@ -0,0 +1,46 @@
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from '@service'
import { Page } from '@utils'
const API_URL = '/reserve-item-service/api/v1/locations'
export interface ILocation {
locationId?: number
locationName: string
sortSeq: number
isUse: boolean
}
export const locationService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
useSWR<Page, AxiosError>(
[`${API_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: (id: number) =>
axios.get(`${API_URL}/${id}`, {
headers: common.headers,
}),
save: (data: ILocation) =>
axios.post(API_URL, data, {
headers: common.headers,
}),
update: (id: number, data: ILocation) =>
axios.put(`${API_URL}/${id}`, data, {
headers: common.headers,
}),
delete: (id: number) =>
axios.delete(`${API_URL}/${id}`, {
headers: common.headers,
}),
updateUse: (id: number, isUse: boolean) =>
axios.put(`${API_URL}/${id}/${isUse}`, null, {
headers: common.headers,
}),
getList: () =>
axios.get(`${API_URL}/combo`, {
headers: common.headers,
}),
}

View File

@@ -0,0 +1,56 @@
import { loginFormType } from '@components/Auth/LoginForm'
import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME } from '@constants/env'
import axios from 'axios'
const JWT_EXPIRED_TIME = 1800000
const LOGIN_URL = `/user-service/login`
const CLIENT_REFRESH_URL = `/client/refresh`
const onSuccessLogin = (result: any) => {
axios.defaults.headers.common[CLAIM_NAME] = result[ACCESS_TOKEN]
axios.defaults.headers.common[AUTH_USER_ID] = result[AUTH_USER_ID]
// access-token 만료 1분 전에 로그인 연장
setTimeout(loginSerivce.silentRefresh, JWT_EXPIRED_TIME - 60000)
}
export const loginSerivce = {
login: (data: loginFormType) => {
return new Promise<string>(async (resolve, reject) => {
try {
const result = await fetch(`/api/proxy${LOGIN_URL}`, {
method: 'POST',
body: JSON.stringify(data),
})
if (result.ok === true) {
onSuccessLogin(await result.json())
resolve('success')
} else {
reject('noAuth')
}
} catch (error) {
reject(error)
}
})
},
silentRefresh: async () => {
try {
// const result = await axios.put(CLIENT_REFRESH_URL)
const result = await fetch(`/api/proxy${CLIENT_REFRESH_URL}`, {
method: 'PUT',
})
if (result) {
onSuccessLogin(await result.json())
}
} catch (error) {
console.warn('refresh token 만료로 인한 로그아웃!!!!')
fetch('/api/v1/token')
.then(res => {
console.info('fetch', res)
})
.catch(error => {
console.info('fetch error', error)
})
}
},
}

View File

@@ -0,0 +1,145 @@
import { common } from '@service'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
const MENU_API = '/portal-service/api/v1/menus'
export interface IMenuSavePayload {
name: string
parentId?: number
siteId?: number
sortSeq: number
level: number
isUse: boolean
isShow: boolean
}
export interface IMenuTree extends IMenuSavePayload {
menuId: number
icon: string
index?: number
children: IMenuTree[]
}
export interface IMenuInfoForm {
menuId: number
menuKorName: string
menuEngName: string
menuType: string
menuTypeName?: string
urlPath?: string
connectId?: number
connectName?: string
subName?: string
icon?: string
description?: string
isUse: boolean
isShow: boolean
isBlank: boolean
}
export interface ISite {
id: number
name: string
isUse: boolean
}
export const menuService = {
getMenus: () => {
return new Promise<IMenuTree[]>(async (resolve, rejects) => {
try {
const result = await axios.get('/portal-service/api/v1/1/menus')
if (result) {
resolve(result.data)
} else {
resolve([])
}
} catch (error) {
rejects(error)
}
})
},
getSites: () => {
return new Promise<ISite[]>(async (resolve, rejects) => {
try {
const result = await axios.get(`/portal-service/api/v1/sites`)
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
getTreeMenus: (siteId: number) => {
return useSWR<IMenuTree[], AxiosError>(
`${MENU_API}/${siteId}/tree`,
url => common.fetcher(url, {}),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
getMenu: (menuId: number) => {
return new Promise<IMenuInfoForm>(async (resolve, rejects) => {
try {
const result = await axios.get(`${MENU_API}/${menuId}`)
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
save: (data: IMenuSavePayload) => {
return new Promise<IMenuTree>(async (resolve, rejects) => {
try {
const result = await axios.post(MENU_API, data, {
headers: common.headers,
})
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
updateName: (menuId: number, name: string) => {
return new Promise<IMenuTree>(async (resolve, rejects) => {
try {
const result = await axios.put(`${MENU_API}/${menuId}/${name}`)
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
updateDnD: (siteId: number, data: IMenuTree[]) => {
return new Promise<IMenuTree[]>(async (resolve, rejects) => {
try {
const result = await axios.put(`${MENU_API}/${siteId}/tree`, data, {
headers: common.headers,
})
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
delete: (menuId: number) => {
return new Promise(async (resolve, rejects) => {
try {
const result = await axios.delete(`${MENU_API}/${menuId}`)
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
update: (menuId: number, data: IMenuInfoForm) => {
return new Promise<IMenuInfoForm>(async (resolve, rejects) => {
try {
const result = await axios.put(`${MENU_API}/${menuId}`, data, {
headers: common.headers,
})
resolve(result?.data)
} catch (error) {
rejects(error)
}
})
},
}

View File

@@ -0,0 +1,34 @@
import { common } from '@service'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
const MENU_ROLE_API = '/portal-service/api/v1/menu-roles'
export interface IMenuRole {
children?: IMenuRole[]
icon?: string
isChecked: boolean
level?: number
engName: string
id: number
korName: string
menuRoleId?: number
parentId?: number
roleId?: string
sortSeq?: number
}
export const menuRoleService = {
search: (roleId: string, siteId: number) => {
return useSWR<IMenuRole[], AxiosError>(
`${MENU_ROLE_API}/${roleId.toLowerCase()}/${siteId}`,
url => common.fetcher(url, {}),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
save: (data: IMenuRole[]) => {
return axios.post(`${MENU_ROLE_API}`, data, {
headers: common.headers,
})
},
}

View File

@@ -0,0 +1,96 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface PolicySavePayload {
type: string
isUse: boolean
title: string
regDate: Date
contents: string
}
/**
* request payload
*/
export interface PolicyPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
id?: string
data?: PolicySavePayload
isUse?: boolean
}
const POLICY_API = '/portal-service/api/v1/policies'
const POLICY_TYPE_API = '/portal-service/api/v1/code-details/policy/codes'
/**
* 이용약관 관리 서비스
*/
export const policyService = {
url: POLICY_API,
typeUrl: POLICY_TYPE_API,
getTypeList: () => {
return axios.get(POLICY_TYPE_API)
},
getOne: (id: string) => {
return axios.get(`${POLICY_API}/${id}`)
},
search: ({ keywordType, keyword, size, page }: SearchPayload) => {
return useSWR<Page, AxiosError>(
[`${POLICY_API}?size=${size}&page=${page}`, keywordType, keyword],
(url, keywordType, keyword) =>
common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
delete: async ({ id, callback, errorCallback }: PolicyPayload) => {
try {
const result = await axios.delete(`${POLICY_API}/${id}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: PolicyPayload) => {
try {
const result = await axios.post(`${POLICY_API}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({ callback, errorCallback, id, data }: PolicyPayload) => {
try {
const result = await axios.put(`${POLICY_API}/${id}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
updateUse: async ({ callback, errorCallback, id, isUse }: PolicyPayload) => {
try {
const result = await axios.put(`${POLICY_API}/${id}/${isUse}`, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,139 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface PostsSavePayload {
boardNo: number
postsNo?: number
postsTitle: string
noticeAt: boolean
postsContent: string
postsAnswerContent?: string
attachmentCode?: string
createdBy?: string
createdName?: string
createdDate?: string
readCount?: number
deleteAt?: number
commentCount?: number
}
/**
* request payload
*/
export interface PostsPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
boardNo?: number
postsNo?: number
data?: PostsSavePayload | PostsDeletePayload[]
}
/**
* 삭제/복원/완전삭제 시 데이터 타입
*/
export interface PostsDeletePayload {
boardNo: number
postsNo: number
}
/**
* 포털 서비스 게시물 API URL
*/
const POSTS_URL = '/board-service/api/v1/posts'
/**
* 게시물 관리 서비스
*/
export const postsService = {
search: (
boardNo: number,
{ keywordType, keyword, size, page }: SearchPayload,
) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[
`${POSTS_URL}/${boardNo}?size=${size}&page=${page}`,
keywordType,
keyword,
],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (boardNo: number, postsNo: number) =>
axios.get(`${POSTS_URL}/${boardNo}/${postsNo}`),
save: async ({ boardNo, callback, errorCallback, data }: PostsPayload) => {
try {
const result = await axios.post(`${POSTS_URL}/${boardNo}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({
boardNo,
postsNo,
callback,
errorCallback,
data,
}: PostsPayload) => {
try {
const result = await axios.put(
`${POSTS_URL}/${boardNo}/${postsNo}`,
data,
{
headers: common.headers,
},
)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
remove: async ({ callback, errorCallback, data }: PostsPayload) => {
try {
const result = await axios.put(`${POSTS_URL}/remove`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
restore: async ({ callback, errorCallback, data }: PostsPayload) => {
try {
const result = await axios.put(`${POSTS_URL}/restore`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
delete: async ({ callback, errorCallback, data }: PostsPayload) => {
try {
const result = await axios.put(`${POSTS_URL}/delete`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,99 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface PrivacySavePayload {
privacyTitle: string
privacyContent: string
useAt: boolean
}
/**
* request payload
*/
export interface PrivacyPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
privacyNo?: string
data?: PrivacySavePayload
useAt?: boolean
}
/**
* 포털 서비스 개인정보처리방침 API URL
*/
const PRIVACY_URL = '/portal-service/api/v1/privacies'
/**
* 개인정보처리방침 관리 서비스
*/
export const privacyService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${PRIVACY_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (privacyNo: string) => axios.get(`${PRIVACY_URL}/${privacyNo}`),
delete: async ({ privacyNo, callback, errorCallback }: PrivacyPayload) => {
try {
const result = await axios.delete(`${PRIVACY_URL}/${privacyNo}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: PrivacyPayload) => {
try {
const result = await axios.post(PRIVACY_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({
callback,
errorCallback,
privacyNo,
data,
}: PrivacyPayload) => {
try {
const result = await axios.put(`${PRIVACY_URL}/${privacyNo}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
updateUseAt: async ({
callback,
errorCallback,
privacyNo,
useAt,
}: PrivacyPayload) => {
try {
const result = await axios.put(`${PRIVACY_URL}/${privacyNo}/${useAt}`, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,94 @@
import { common, SearchPayload } from '@service'
import { Page } from '@utils'
import axios, { AxiosError, AxiosResponse } from 'axios'
import {
Control,
FormState,
UseFormGetValues,
UseFormRegister,
UseFormSetValue,
} from 'react-hook-form'
import useSWR from 'swr'
import { IReserveItemRelation } from './ReserveItem'
const API_URL = '/reserve-check-service/api/v1/reserves'
export interface IReserve {
reserveId: string
reserveItemId: number
reserveItem: IReserveItemRelation
reserveQty: number
reserveStartDate: Date
reserveEndDate: Date
reservePurposeContent: string
attachmentCode: string
reserveStatusId: string
userId: string
userName: string
userContactNo: string
userEmail: string
}
export interface ReserveSavePayload {
reserveItemId: number
locationId: number
categoryId: string
reserveQty: number
reservePurposeContent: string
attachmentCode: string
reserveStartDate: Date
reserveEndDate: Date
reserveStatusId: string
userId: string
userContactNo: string
userEmail: string
}
export interface ReserveFormProps {
control: Control<IReserve, object>
formState: FormState<IReserve>
register?: UseFormRegister<IReserve>
getValues?: UseFormGetValues<IReserve>
setValue?: UseFormSetValue<IReserve>
}
interface ReserveSearchPayload extends SearchPayload {
locationId?: string
categoryId?: string
}
export const reserveService = {
search: ({
keywordType,
keyword,
size,
page,
locationId,
categoryId,
}: ReserveSearchPayload) =>
useSWR<Page, AxiosError>(
[
`${API_URL}?size=${size}&page=${page}`,
keywordType,
keyword,
locationId,
categoryId,
],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: (reserveId: string) =>
axios.get<any, AxiosResponse<IReserve>>(`${API_URL}/${reserveId}`),
save: (data: ReserveSavePayload) => axios.post(API_URL, data),
update: (reserveId: string, data: ReserveSavePayload) =>
axios.put(`${API_URL}/${reserveId}`, data),
cancel: (reserveId: string, reason: string) =>
axios.put(`${API_URL}/cancel/${reserveId}`, {
reasonCancelContent: reason,
}),
approve: (reserveId: string) => axios.put(`${API_URL}/approve/${reserveId}`),
getInventories: (reserveItemId: number, startDate: string, endDate: string) =>
axios.get(
`${API_URL}/${reserveItemId}/inventories?startDate=${startDate}&endDate=${endDate}`,
),
}

View File

@@ -0,0 +1,163 @@
import { common, SearchPayload } from '@service'
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import {
Control,
FormState,
UseFormGetValues,
UseFormRegister,
} from 'react-hook-form'
import useSWR from 'swr'
import { ILocation } from './Location'
const API_URL = '/reserve-item-service/api/v1/reserve-items'
const CODE_API_URL = (code: string) =>
`/portal-service/api/v1/code-details/${code}/codes`
export interface IReserveItemList {
reserveItemId: number
reserveItemName: string
locationId: number
categoryId: string
totalQty: number
inventoryQty: number
isUse: boolean
createDate: Date
isPossible: boolean
}
export interface IReserveItem {
reserveItemId: number
reserveItemName: string
locationId: number
categoryId: string
prevTotalQty: number
totalQty: number
inventoryQty: number
operationStartDate: Date
operationEndDate: Date
reserveMethodId: string
reserveMeansId?: string
requestStartDate?: Date
requestEndDate?: Date
isPeriod?: boolean
periodMaxCount?: number
externalUrl?: string
selectionMeansId: string
isPaid: boolean
usageCost?: number
isUse: boolean
purpose?: string
address?: string
targetId?: string
excluded?: string
homepage?: string
contact?: string
managerDept?: string
managerName?: string
managerContact?: string
}
export interface IReserveItemRelation {
reserveItemId: number
reserveItemName: string
locationId: number
location: ILocation
categoryId: string
categoryName: string
totalQty: number
inventoryQty: number
operationStartDate: string
operationEndDate: string
reserveMethodId: string
reserveMethodName: string
reserveMeansId: string
reserveMeansName: string
requestStartDate: string
requestEndDate: string
isPeriod: true
periodMaxCount: number
externalUrl: string
selectionMeansId: string
selectionMeansName: string
isPaid: true
usageCost: number
isUse: true
purpose: string
address: string
targetId: string
targetName: string
excluded: string
homepage: string
contact: string
managerDept: string
managerName: string
managerContact: string
}
export interface ReserveItemFormProps {
control: Control<IReserveItem, object>
formState: FormState<IReserveItem>
register?: UseFormRegister<IReserveItem>
getValues?: UseFormGetValues<IReserveItem>
}
interface ReserveItemSearchPayload extends SearchPayload {
locationId?: string
categoryId?: string
isUse?: boolean
}
export const reserveItemService = {
search: ({
keywordType,
keyword,
size,
page,
locationId,
categoryId,
isUse = false,
}: ReserveItemSearchPayload) => {
return useSWR<Page, AxiosError>(
[
`${API_URL}?size=${size}&page=${page}`,
keywordType,
keyword,
locationId,
categoryId,
isUse,
],
url =>
common.fetcher(url, {
keywordType,
keyword,
locationId,
categoryId,
isUse,
}),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
},
get: (id: number) =>
axios.get(`${API_URL}/${id}`, {
headers: common.headers,
}),
getWithRelation: (id: number) => axios.get(`${API_URL}/relations/${id}`),
save: (data: IReserveItem) =>
axios.post(API_URL, data, {
headers: common.headers,
}),
update: (id: number, data: IReserveItem) =>
axios.put(`${API_URL}/${id}`, data, {
headers: common.headers,
}),
updateUse: (id: number, isUse: boolean) =>
axios.put(`${API_URL}/${id}/${isUse}`, null, {
headers: common.headers,
}),
getCode: (codeId: string) =>
axios.get(CODE_API_URL(codeId), {
headers: common.headers,
}),
}

View File

@@ -0,0 +1,28 @@
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { Page } from '@utils'
import { common, SearchPayload } from './common'
/**
* 사용자 서비스 권한 API URL
*/
const ROLE_URL = '/user-service/api/v1/roles'
export interface IRole {
createdDate?: Date
roleContent?: string
roleId: string
roleName: string
}
// eslint-disable-next-line import/prefer-default-export
export const roleService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${ROLE_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
searchAll: () => axios.get(`${ROLE_URL}/all`),
}

View File

@@ -0,0 +1,75 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
/**
* 저장 시 데이터 타입
*/
export interface RoleAuthorizationSavePayload {
roleId: string
authorizationNo: number
}
/**
* request payload
*/
export interface RoleAuthorizationPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
data?: RoleAuthorizationSavePayload[]
}
/**
* 사용자 서비스 권한 인가 API URL
*/
const ROLE_AUTHORIZATION_URL = '/user-service/api/v1/role-authorizations'
/**
* 이용약관 관리 서비스
*/
export const roleAuthorizationService = {
search: (
roleId: string,
{ keywordType, keyword, size, page }: SearchPayload,
) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[
`${ROLE_AUTHORIZATION_URL}?size=${size}&page=${page}`,
roleId,
keywordType,
keyword,
],
url => common.fetcher(url, { roleId, keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
save: async ({ callback, errorCallback, data }: RoleAuthorizationPayload) => {
try {
const result = await axios.post(ROLE_AUTHORIZATION_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
delete: async ({
callback,
errorCallback,
data,
}: RoleAuthorizationPayload) => {
try {
const result = await axios.put(ROLE_AUTHORIZATION_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,54 @@
import { SITE_ID } from '@constants/env'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common } from './common'
const STATISTICS_API = `/portal-service/api/v1/statistics`
export interface IBarChartData {
year: number
month: number
day: number
x: string
y: number
}
export interface DailyPayload {
year: number
month: number
}
export const statisticsService = {
getMonthly: (siteId: number) => {
const { data, mutate } = useSWR<IBarChartData[], AxiosError>(
`${STATISTICS_API}/monthly/${siteId}`,
url => common.fetcher(url, {}),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
return {
monthly: data,
monthlyMutate: mutate,
}
},
getDaily: (siteId: number, payload: DailyPayload) => {
const { data, mutate } = useSWR<IBarChartData[], AxiosError>(
`${STATISTICS_API}/daily/${siteId}?year=${payload.year}&month=${payload.month}`,
url => common.fetcher(url, {}),
{ revalidateOnFocus: false, errorRetryCount: 0 },
)
return {
daily: data,
dailyMutate: mutate,
}
},
getSites: () => {
return axios.get(`/portal-service/api/v1/sites`)
},
save: (uuid: string) => {
return axios.post(`${STATISTICS_API}/${uuid}`, {
Headers: common.headers,
})
},
}

View File

@@ -0,0 +1,91 @@
import { Page } from '@utils'
import axios, { AxiosError } from 'axios'
import useSWR from 'swr'
import { common, SearchPayload } from './common'
export interface IUser {
email: string
lastLoginDate: Date
loginFailCount: number
roleId: string
roleName: string
userId: string
userName: string
userStateCode: string
userStateCodeName: string
}
/**
* 저장 시 데이터 타입
*/
export interface UserSavePayload {
email: string
password: string
userName: string
roleId: string
userStateCode: string
}
/**
* request payload너
*/
export interface UserPayload {
callback: () => any
errorCallback: (error: AxiosError) => void
userId?: string
data?: UserSavePayload
useAt?: boolean
}
/**
* 포털 서비스 배너 API URL
*/
const USER_URL = '/user-service/api/v1/users'
/**
* 배너 관리 서비스
*/
export const userService = {
search: ({ keywordType, keyword, size, page }: SearchPayload) =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useSWR<Page, AxiosError>(
[`${USER_URL}?size=${size}&page=${page}`, keywordType, keyword],
url => common.fetcher(url, { keywordType, keyword }),
{ revalidateOnFocus: false, errorRetryCount: 0 },
),
get: async (userId: string) => axios.get(`${USER_URL}/${userId}`),
delete: async ({ userId, callback, errorCallback }: UserPayload) => {
try {
const result = await axios.delete(`${USER_URL}/delete/${userId}`)
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
save: async ({ callback, errorCallback, data }: UserPayload) => {
try {
const result = await axios.post(USER_URL, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
update: async ({ callback, errorCallback, userId, data }: UserPayload) => {
try {
const result = await axios.put(`${USER_URL}/${userId}`, data, {
headers: common.headers,
})
if (result) {
callback()
}
} catch (error) {
errorCallback(error)
}
},
}

View File

@@ -0,0 +1,38 @@
import axios from 'axios'
export interface IResponse {
err?: {
status: number
message: string
}
}
export interface IReqeust {
url: string
}
const headers = {
'Content-Type': 'application/json',
}
export interface SearchPayload {
keywordType?: string
keyword?: string
size?: number
page?: number
}
//목록 데이터 조회하는 fetcher
const fetcher = async (url: string, param: {}) => {
const res = await axios.get(url, {
params: param,
headers,
})
return res.data
}
export const common = {
headers,
fetcher,
}

View File

@@ -0,0 +1,21 @@
export * from './Policy'
export * from './Role'
export * from './Authorization'
export * from './RoleAuthorization'
export * from './Attachment'
export * from './File'
export * from './common'
export * from './Code'
export * from './Content'
export * from './Privacy'
export * from './Login'
export * from './Board'
export * from './Posts'
export * from './Comment'
export * from './Menu'
export * from './Banner'
export * from './Statistics'
export * from './Location'
export * from './ReserveItem'
export * from './Reserve'
export * from './User'