Files
egovframe-msa-edu/frontend/admin/src/pages/policy/index.tsx
2021-10-21 09:03:17 +09:00

295 lines
6.9 KiB
TypeScript

import { GridButtons } from '@components/Buttons'
import Search from '@components/Search'
import CustomDataGrid from '@components/Table/CustomDataGrid'
import { GRID_PAGE_SIZE } from '@constants'
import usePage from '@hooks/usePage'
import useSearchTypes from '@hooks/useSearchType'
// 내부 컴포넌트 및 custom hook, etc...
import { convertStringToDateFormat } from '@libs/date'
// material-ui deps
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import Switch from '@material-ui/core/Switch'
import {
GridCellParams,
GridColDef,
GridValueFormatterParams,
GridValueGetterParams,
} from '@material-ui/data-grid'
//api
import { policyService } from '@service'
import { conditionAtom, errorStateSelector } from '@stores'
import { Page, rownum } from '@utils'
import { AxiosError } from 'axios'
import { GetServerSideProps, NextPage } from 'next'
import { TFunction, useTranslation } from 'next-i18next'
import { useRouter } from 'next/router'
import React, { useCallback, useMemo } from 'react'
// 상태관리 recoil
import { useRecoilValue, useSetRecoilState } from 'recoil'
// material-ui style
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
flexGrow: 1,
'& .MuiOutlinedInput-input': {
padding: theme.spacing(1),
},
},
}),
)
//그리드 컬럼 정의
type ColumnsType = (
data: Page,
typeList: IPolicyType[],
deletePolicy: (id: string) => void,
updatePolicy: (id: string) => void,
toggleIsUse: (event: React.ChangeEvent<HTMLInputElement>, id: string) => void,
t?: TFunction,
) => GridColDef[]
const getColumns: ColumnsType = (
data,
typeList,
deletePolicy,
updatePolicy,
toggleIsUse,
t,
) => {
return [
{
field: 'rownum',
headerName: t('common.no'),
headerAlign: 'center',
align: 'center',
sortable: false,
valueGetter: (params: GridValueGetterParams) =>
rownum(data, params.api.getRowIndex(params.id), 'desc'),
},
{
field: 'type',
headerName: t('common.type'),
headerAlign: 'center',
align: 'center',
width: 150,
sortable: false,
valueGetter: (params: GridValueGetterParams) => {
const type = typeList?.find(item => item.codeId === params.value)
return type?.codeName || ''
},
},
{
field: 'title',
headerName: t('policy.title'),
headerAlign: 'center',
width: 200,
sortable: false,
},
{
field: 'isUse',
headerName: t('common.use_at'),
headerAlign: 'center',
align: 'center',
width: 120,
sortable: false,
renderCell: (params: GridCellParams) => (
<Switch
checked={Boolean(params.value)}
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
toggleIsUse(event, params.row.id)
}
/>
),
},
{
field: 'regDate',
headerName: t('common.created_datetime'),
headerAlign: 'center',
align: 'center',
width: 120,
sortable: false,
valueFormatter: (params: GridValueFormatterParams) => {
return convertStringToDateFormat(
params.value as string,
'yyyy-MM-dd HH:mm:ss',
)
},
},
{
field: 'id',
headerName: t('common.manage'),
headerAlign: 'center',
align: 'center',
width: 200,
sortable: false,
renderCell: (params: GridCellParams) => (
<GridButtons
id={params.value as string}
handleDelete={deletePolicy}
handleUpdate={updatePolicy}
/>
),
},
]
}
const conditionKey = 'policy'
export interface IPolicyType {
codeId: string
codeName: string
sortSeq: number
}
export interface IPolicyProps {
typeList: IPolicyType[]
}
// 실제 render되는 컴포넌트
const Policy: NextPage<IPolicyProps> = ({ typeList }) => {
// props 및 전역변수
// const { id } = props
const classes = useStyles()
const route = useRouter()
const { t } = useTranslation()
/**
* 상태관리 필요한 훅
*/
//조회조건 상태관리
const keywordState = useRecoilValue(conditionAtom(conditionKey))
const setErrorState = useSetRecoilState(errorStateSelector)
//현 페이지내 필요한 hook
const { page, setPageValue } = usePage(conditionKey)
//목록 데이터 조회 및 관리
const { data, mutate } = policyService.search({
keywordType: keywordState?.keywordType || 'title',
keyword: keywordState?.keyword || '',
size: GRID_PAGE_SIZE,
page,
})
//조회조건 select items
const searchTypes = useSearchTypes([
{
key: 'title',
label: t('policy.title'),
},
{
key: 'contents',
label: t('comment.comment_content'),
},
])
/**
* 비지니스 로직
*/
//에러 callback
const errorCallback = useCallback((error: AxiosError) => {
setErrorState({
error,
})
}, [])
//삭제
const deletePolicy = useCallback((id: string) => {
policyService.delete({
callback: mutate,
errorCallback,
id,
})
}, [])
//수정 시 상세 화면 이동
const updatePolicy = useCallback((id: string) => {
route.push(`/policy/${id}`)
}, [])
//사용여부 toggle 시 바로 update
const toggleIsUse = useCallback(
async (event: React.ChangeEvent<HTMLInputElement>, id: string) => {
policyService.updateUse({
callback: mutate,
errorCallback,
id,
isUse: event.target.checked,
})
},
[page],
)
// 목록컬럼 재정의 > 컬럼에 비지니스 로직이 필요한 경우
const columns = useMemo(() => {
return getColumns(
data,
typeList,
deletePolicy,
updatePolicy,
toggleIsUse,
t,
)
}, [data])
//목록 조회
const handleSearch = () => {
if (page === 0) {
mutate()
} else {
setPageValue(0)
}
}
//datagrid page change event
const handlePageChange = (page: number, details?: any) => {
setPageValue(page)
}
return (
<div className={classes.root}>
<Search
keywordTypeItems={searchTypes}
handleSearch={handleSearch}
handleRegister={() => {
route.push('policy/-1')
}}
conditionKey={conditionKey}
/>
<CustomDataGrid
classes={classes}
rows={data?.content}
columns={columns}
rowCount={data?.totalElements}
paginationMode="server"
pageSize={GRID_PAGE_SIZE}
page={page}
onPageChange={handlePageChange}
/>
</div>
)
}
export const getServerSideProps: GetServerSideProps = async context => {
let typeList: IPolicyType[] = []
try {
const result = await policyService.getTypeList()
if (result) {
typeList = result.data
}
} catch (error) {
console.error(`policy list getServerSideProps error ${error.message}`)
}
return {
props: {
typeList,
},
}
}
export default Policy