-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 동적으로 테이블이 변경되는 기능을 구현한다 #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,50 @@ | ||
| import { CssBaseline } from '@mui/material'; | ||
| import 'common.css'; | ||
|
|
||
| import { useState } from 'react'; | ||
|
|
||
| import { memberTokenStore } from '@store/memberTokenStore.ts'; | ||
|
|
||
| import { stationMockData } from '@mock'; | ||
|
|
||
| import { useFetchStations } from '@hook/stations/useFetchStations.ts'; | ||
|
|
||
| import ToastContainer from '@common/Toast/ToastContainer'; | ||
|
|
||
| import LoginModalContent from '@component/Login'; | ||
| import ModalContainer from '@component/ModalContainer'; | ||
| import NavigationContainer from '@component/Navigation'; | ||
| import AdminTable from '@component/Table'; | ||
|
|
||
| import { MENU_LIST } from '@constant'; | ||
|
|
||
| import { getColumnsByTitle, stationColumns } from '@type'; | ||
|
|
||
|
|
||
| function App() { | ||
| const [tableTitle, setTableTitle] = useState('충전소 관리'); | ||
| const [tableColumn, setTableColumn] = useState(stationColumns); | ||
| const [tableData, setTableData] = useState(stationMockData); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기 밑에도 개행 줘도 될 것 같아여 |
||
| const token = memberTokenStore.getState(); | ||
| const { lastPage, stationSummaryList } = useFetchStations(token, 1); | ||
| if (token === '') return <LoginModalContent />; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 개행 주세여 |
||
|
|
||
| const setTable = (title: string) => { | ||
| setTableTitle(title); | ||
| setTableData(stationSummaryList); | ||
| setTableColumn(getColumnsByTitle(title)); | ||
| }; | ||
| // const [page, setPage] = useState(1); | ||
|
|
||
| return ( | ||
| <> | ||
| <ToastContainer /> | ||
| <ModalContainer /> | ||
| <CssBaseline /> | ||
| <NavigationContainer title="ADMIN" menus={MENU_LIST} /> | ||
| <AdminTable title="전체 충전소" /> | ||
| <NavigationContainer title="ADMIN" menus={MENU_LIST} tableHandler={setTable} /> | ||
| <AdminTable title={tableTitle} data={tableData} columns={tableColumn} lastPage={lastPage} /> | ||
| </> | ||
| ); | ||
| } | ||
|
|
||
| export default App; | ||
| export default App; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,7 @@ const headerTitleCss = css` | |
| xs: none; | ||
| sm: block; | ||
| } | ||
|
|
||
| flex-grow: 1; | ||
| margin-left: 4px; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,9 +17,10 @@ import type { Menu } from '@type'; | |
|
|
||
| interface NavigationProps { | ||
| menus: readonly Menu[]; | ||
| onClick: (title: string) => void; | ||
| } | ||
|
|
||
| export const NavigationMenu = ({ menus }: NavigationProps) => { | ||
| export const NavigationMenu = ({ menus, onClick }: NavigationProps) => { | ||
| const [memberToken, setMemberToken] = useExternalState(memberTokenStore); | ||
| const { openModal } = modalActions; | ||
| const { showToast } = toastActions; | ||
|
|
@@ -32,12 +33,11 @@ export const NavigationMenu = ({ menus }: NavigationProps) => { | |
|
|
||
| const isLoggedIn = memberToken !== ''; | ||
|
|
||
| const handleClickMenu = (menu: Menu) => { | ||
| if (menu === '간편 로그인' && !isLoggedIn) { | ||
| const handleClickMenu = () => { | ||
| if (!isLoggedIn) { | ||
| openModal(<LoginModalContent />, 500); | ||
| } | ||
|
|
||
| if (menu === '간편 로그인' && isLoggedIn) { | ||
| if (isLoggedIn) { | ||
| logout(); | ||
| } | ||
| }; | ||
|
|
@@ -48,13 +48,16 @@ export const NavigationMenu = ({ menus }: NavigationProps) => { | |
| showToast('로그아웃 되었습니다', 'success'); | ||
| }; | ||
|
|
||
| return menus.map((menu, index) => ( | ||
| <Button | ||
| key={index} | ||
| sx={{ color: '#fff', wordBreak: 'keep-all' }} | ||
| onClick={() => handleClickMenu(menu)} | ||
| > | ||
| {menu === '간편 로그인' && isLoggedIn ? '로그아웃' : menu} | ||
| </Button> | ||
| )); | ||
| return ( | ||
| <> | ||
| {menus.map((menu, index) => ( | ||
| <Button key={index} sx={{ color: '#fff' }} onClick={() => onClick(menu)}> | ||
| {menu} | ||
| </Button> | ||
| ))} | ||
| <Button sx={{ color: '#fff', wordBreak: 'keep-all' }} onClick={() => handleClickMenu()}> | ||
| {isLoggedIn ? '로그아웃' : '간편로그인'} | ||
| </Button>{' '} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| </> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,32 @@ | ||
| import type { Meta } from '@storybook/react'; | ||
|
|
||
| import { stationMockData } from '@mock'; | ||
|
|
||
| import type { StationDetails } from '@type'; | ||
| import { stationColumns } from '@type'; | ||
|
|
||
| import type { TableProps } from './AdminTable'; | ||
| import AdminTable from './AdminTable'; | ||
|
|
||
| type Props = TableProps<StationDetails, keyof StationDetails>; | ||
|
|
||
| const meta = { | ||
| component: AdminTable, | ||
| tags: ['autodocs'], | ||
| args: { | ||
| title: '전체 충전소', | ||
| data: stationMockData, | ||
| columns: stationColumns, | ||
| }, | ||
| argTypes: { | ||
| title: { | ||
| description: '페이지 제목을 변경할 수 있습니다.', | ||
| }, | ||
| }, | ||
| } satisfies Meta<typeof AdminTable>; | ||
| } as Meta<Props>; | ||
|
|
||
| export default meta; | ||
|
|
||
| export const Default = (args: TableProps) => { | ||
| export const Default = (args: Props) => { | ||
| return <AdminTable {...args} />; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,107 +3,52 @@ import TableBody from '@mui/material/TableBody'; | |
| import TableCell from '@mui/material/TableCell'; | ||
| import TableRow from '@mui/material/TableRow'; | ||
|
|
||
| import { modalActions } from '@store/modalStateStore'; | ||
| import { modalActions } from '@store/modalStateStore.ts'; | ||
|
|
||
| import { stationEditMock } from '@mock'; | ||
|
|
||
| import Form from '@component/Form'; | ||
|
|
||
| import { ROWS_PER_PAGE } from '@constant'; | ||
| import type { ColumnType } from '@type'; | ||
|
|
||
| import type { StationProps } from '@type'; | ||
|
|
||
| interface Props { | ||
| elements: StationProps[]; | ||
| interface TableRowsProps<T, K extends keyof T> { | ||
| data: Array<T>; | ||
| columns: Array<ColumnType<T, K>>; | ||
| } | ||
|
|
||
| // TODO: 하드 코딩 없앨 것 | ||
| function AdminTableBody({ elements }: Props) { | ||
| const AdminTableBody = <T, K extends keyof T>({ data, columns }: TableRowsProps<T, K>) => { | ||
| const { openModal } = modalActions; | ||
|
|
||
| const handleOpenModal = () => { | ||
| function handleOpenModal() { | ||
|
Comment on lines
+19
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 컴포넌트는 |
||
| openModal(<Form element={stationEditMock} />); | ||
| }; | ||
|
|
||
| const emptyRows = ROWS_PER_PAGE - Math.min(ROWS_PER_PAGE, elements.length); | ||
|
|
||
| return ( | ||
| <TableBody> | ||
| {elements.map((element) => ( | ||
| <TableRow key={element.stationId}> | ||
| <TableCell | ||
| align="center" | ||
| css={tableItemCommonCss} | ||
| sx={{ minWidth: 140, height: 40, cursor: 'pointer' }} | ||
| component="th" | ||
| scope="row" | ||
| onClick={handleOpenModal} | ||
| > | ||
| {element.stationId} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {element.stationName} | ||
| </TableCell> | ||
| <TableCell | ||
| align="center" | ||
| css={[tableItemSizeCss, tableItemCommonCss]} | ||
| sx={{ minWidth: 320 }} | ||
| > | ||
| {element.stationName} | ||
| </TableCell> | ||
| <TableCell align="center" css={tableItemCommonCss} sx={{ minWidth: 320 }}> | ||
| {element.address} | ||
| </TableCell> | ||
| <TableCell align="center" css={tableItemCommonCss} sx={{ minWidth: 280 }}> | ||
| {element.detailLocation} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {element.companyName} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {element.contact} | ||
| </TableCell> | ||
| <TableCell align="center" css={tableItemCommonCss}> | ||
| {String(element.isParkingFree)} | ||
| </TableCell> | ||
| <TableCell align="center" css={tableItemCommonCss}> | ||
| {String(element.isPrivate)} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {element.latitude} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {element.longitude} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {element.operationTime} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {String(element.privateReason)} | ||
| </TableCell> | ||
| <TableCell align="center" css={[tableItemSizeCss, tableItemCommonCss]}> | ||
| {String(element.stationState)} | ||
| </TableCell> | ||
| </TableRow> | ||
| ))} | ||
|
|
||
| {emptyRows > 0 && ( | ||
| <TableRow sx={{ height: 76 * emptyRows }}> | ||
| <TableCell /> | ||
| </TableRow> | ||
| )} | ||
| </TableBody> | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| const rows = data.map((row, index) => { | ||
| return ( | ||
| <TableRow css={tableItemSizeCss} key={`row-${index}`}> | ||
| {columns.map((column, index2) => { | ||
| return ( | ||
| <TableCell css={tableItemCommonCss} key={`cell-${index2}`} onClick={handleOpenModal}> | ||
| {`${row[column.key]}`} | ||
| </TableCell> | ||
| ); | ||
| })} | ||
| </TableRow> | ||
| ); | ||
| }); | ||
| return <TableBody>{rows}</TableBody>; | ||
| }; | ||
|
|
||
| const tableItemSizeCss = css` | ||
| min-width: 200px; | ||
| height: 76px; | ||
| `; | ||
|
|
||
| const tableItemCommonCss = css` | ||
| border-bottom: 0; | ||
| flex: 1; | ||
| overflow: hidden; | ||
| text-overflow: ellipsis; | ||
| white-space: nowrap; | ||
| text-align: center; | ||
| `; | ||
|
|
||
| export default AdminTableBody; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stationColumns이거 확인해보니까tableHeads/categories던데 이름 바꾸는게 어떨까요?