Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions src/App.tsx
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stationColumns 이거 확인해보니까 tableHeads/categories던데 이름 바꾸는게 어떨까요?

const [tableData, setTableData] = useState(stationMockData);
Copy link
Contributor

Choose a reason for hiding this comment

The 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 />;
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
1 change: 1 addition & 0 deletions src/components/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const headerTitleCss = css`
xs: none;
sm: block;
}

flex-grow: 1;
margin-left: 4px;

Expand Down
5 changes: 3 additions & 2 deletions src/components/Navigation/NavigationContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import type { Menu } from '@type';
interface NavigationContainerProps {
title: string;
menus: readonly Menu[];
tableHandler: (title: string) => void;
}

function NavigationContainer({ title, menus }: NavigationContainerProps) {
function NavigationContainer({ title, menus, tableHandler }: NavigationContainerProps) {
return (
<Navigation title={title}>
<NavigationMenu menus={menus} />
<NavigationMenu menus={menus} onClick={tableHandler} />
</Navigation>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Navigation/NavigationMenu.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default meta;
export const Default = () => {
return (
<NavigationMenuContainer>
<NavigationMenu menus={MENU_LIST} />
<NavigationMenu menus={MENU_LIST} onClick={alert} />
</NavigationMenuContainer>
);
};
Expand Down
31 changes: 17 additions & 14 deletions src/components/Navigation/NavigationMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
}
};
Expand All @@ -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>{' '}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{' '} 지워주세요

</>
);
};
13 changes: 11 additions & 2 deletions src/components/Table/AdminTable.stories.tsx
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} />;
};
25 changes: 9 additions & 16 deletions src/components/Table/AdminTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,27 @@ import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableContainer from '@mui/material/TableContainer';

import { memberTokenStore } from '@store/memberTokenStore';

import { useFetchStations } from '@hook/stations/useFetchStations';

import { STATION_DETAILS_CATEGORY_LIST } from '@constant';
import type { ColumnType } from '@type';

import AdminTableBody from './AdminTableBody';
import AdminTableHead from './AdminTableHead';
import AdminTablePagination from './AdminTablePagination';

export interface TableProps {
export interface TableProps<T, K extends keyof T> {
data: T[];
columns: ColumnType<T, K>[];
title: string;
lastPage: number;
}

function AdminTable({ title }: TableProps) {
const token = memberTokenStore.getState();
// const [page, setPage] = useState(1);
const { lastPage, stationSummaryList } = useFetchStations(token, 1);

if (token === '') return <p>로그인이 필요합니다</p>;

function AdminTable<T, K extends keyof T>({ data, columns, title, lastPage }: TableProps<T, K>) {
return (
<Box sx={{ margin: '32px' }}>
<Title>{title}</Title>
<TableContainer component={Paper} css={boxShadowCss}>
<Table sx={{ minWidth: 500, overflowX: 'auto' }} aria-label="정보 표">
<AdminTableHead categoryList={STATION_DETAILS_CATEGORY_LIST} />
<AdminTableBody elements={stationSummaryList} />
<AdminTableHead columns={columns} />
<AdminTableBody data={data} columns={columns} />
</Table>
</TableContainer>
<AdminTablePagination lastPage={lastPage} />
Expand All @@ -54,4 +47,4 @@ const boxShadowCss = css`
0 1px 3px 0 rgba(0, 0, 0, 0.015);
`;

export default AdminTable;
export default AdminTable;
111 changes: 28 additions & 83 deletions src/components/Table/AdminTableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

@feb-dain feb-dain Aug 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

컴포넌트는 function, 이벤트 핸들러 등의 함수는 화살표 함수 써주세요

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;
8 changes: 4 additions & 4 deletions src/components/Table/AdminTableHead.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { Meta } from '@storybook/react';

import { STATION_DETAILS_CATEGORY_LIST } from '@constant';
import { stationColumns } from '@type';

import AdminTableHead from './AdminTableHead';

const meta = {
component: AdminTableHead,
tags: ['autodocs'],
args: {
categoryList: STATION_DETAILS_CATEGORY_LIST,
columns: stationColumns,
},
argTypes: {
categoryList: {
columns: {
control: {
type: 'array',
},
Expand All @@ -23,5 +23,5 @@ const meta = {
export default meta;

export const Default = () => {
return <AdminTableHead categoryList={STATION_DETAILS_CATEGORY_LIST} />;
return <AdminTableHead columns={stationColumns} />;
};
Loading