diff --git a/src/App.tsx b/src/App.tsx
index 5831ac1..d6ffe36 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -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);
+ const token = memberTokenStore.getState();
+ const { lastPage, stationSummaryList } = useFetchStations(token, 1);
+ if (token === '') return ;
+
+ const setTable = (title: string) => {
+ setTableTitle(title);
+ setTableData(stationSummaryList);
+ setTableColumn(getColumnsByTitle(title));
+ };
+ // const [page, setPage] = useState(1);
+
return (
<>
-
-
+
+
>
);
}
-export default App;
+export default App;
\ No newline at end of file
diff --git a/src/components/Navigation/Navigation.tsx b/src/components/Navigation/Navigation.tsx
index d11955d..94982ac 100644
--- a/src/components/Navigation/Navigation.tsx
+++ b/src/components/Navigation/Navigation.tsx
@@ -31,6 +31,7 @@ const headerTitleCss = css`
xs: none;
sm: block;
}
+
flex-grow: 1;
margin-left: 4px;
diff --git a/src/components/Navigation/NavigationContainer.tsx b/src/components/Navigation/NavigationContainer.tsx
index 71db38d..8ad170d 100644
--- a/src/components/Navigation/NavigationContainer.tsx
+++ b/src/components/Navigation/NavigationContainer.tsx
@@ -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 (
-
+
);
}
diff --git a/src/components/Navigation/NavigationMenu.stories.tsx b/src/components/Navigation/NavigationMenu.stories.tsx
index 2da5764..ec4a9da 100644
--- a/src/components/Navigation/NavigationMenu.stories.tsx
+++ b/src/components/Navigation/NavigationMenu.stories.tsx
@@ -26,7 +26,7 @@ export default meta;
export const Default = () => {
return (
-
+
);
};
diff --git a/src/components/Navigation/NavigationMenu.tsx b/src/components/Navigation/NavigationMenu.tsx
index c792af7..ce9ba49 100644
--- a/src/components/Navigation/NavigationMenu.tsx
+++ b/src/components/Navigation/NavigationMenu.tsx
@@ -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(, 500);
}
-
- if (menu === '간편 로그인' && isLoggedIn) {
+ if (isLoggedIn) {
logout();
}
};
@@ -48,13 +48,16 @@ export const NavigationMenu = ({ menus }: NavigationProps) => {
showToast('로그아웃 되었습니다', 'success');
};
- return menus.map((menu, index) => (
-
- ));
+ return (
+ <>
+ {menus.map((menu, index) => (
+
+ ))}
+ {' '}
+ >
+ );
};
diff --git a/src/components/Table/AdminTable.stories.tsx b/src/components/Table/AdminTable.stories.tsx
index 246cb87..104d0fb 100644
--- a/src/components/Table/AdminTable.stories.tsx
+++ b/src/components/Table/AdminTable.stories.tsx
@@ -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;
+
const meta = {
component: AdminTable,
tags: ['autodocs'],
args: {
title: '전체 충전소',
+ data: stationMockData,
+ columns: stationColumns,
},
argTypes: {
title: {
description: '페이지 제목을 변경할 수 있습니다.',
},
},
-} satisfies Meta;
+} as Meta;
export default meta;
-export const Default = (args: TableProps) => {
+export const Default = (args: Props) => {
return ;
};
diff --git a/src/components/Table/AdminTable.tsx b/src/components/Table/AdminTable.tsx
index 4cc9302..2a4e985 100644
--- a/src/components/Table/AdminTable.tsx
+++ b/src/components/Table/AdminTable.tsx
@@ -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 {
+ data: T[];
+ columns: ColumnType[];
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 로그인이 필요합니다
;
-
+function AdminTable({ data, columns, title, lastPage }: TableProps) {
return (
{title}
@@ -54,4 +47,4 @@ const boxShadowCss = css`
0 1px 3px 0 rgba(0, 0, 0, 0.015);
`;
-export default AdminTable;
+export default AdminTable;
\ No newline at end of file
diff --git a/src/components/Table/AdminTableBody.tsx b/src/components/Table/AdminTableBody.tsx
index 41b3ffb..c8f6e21 100644
--- a/src/components/Table/AdminTableBody.tsx
+++ b/src/components/Table/AdminTableBody.tsx
@@ -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 {
+ data: Array;
+ columns: Array>;
}
-// TODO: 하드 코딩 없앨 것
-function AdminTableBody({ elements }: Props) {
+const AdminTableBody = ({ data, columns }: TableRowsProps) => {
const { openModal } = modalActions;
- const handleOpenModal = () => {
+ function handleOpenModal() {
openModal();
- };
-
- const emptyRows = ROWS_PER_PAGE - Math.min(ROWS_PER_PAGE, elements.length);
-
- return (
-
- {elements.map((element) => (
-
-
- {element.stationId}
-
-
- {element.stationName}
-
-
- {element.stationName}
-
-
- {element.address}
-
-
- {element.detailLocation}
-
-
- {element.companyName}
-
-
- {element.contact}
-
-
- {String(element.isParkingFree)}
-
-
- {String(element.isPrivate)}
-
-
- {element.latitude}
-
-
- {element.longitude}
-
-
- {element.operationTime}
-
-
- {String(element.privateReason)}
-
-
- {String(element.stationState)}
-
-
- ))}
-
- {emptyRows > 0 && (
-
-
-
- )}
-
- );
-}
+ }
+
+ const rows = data.map((row, index) => {
+ return (
+
+ {columns.map((column, index2) => {
+ return (
+
+ {`${row[column.key]}`}
+
+ );
+ })}
+
+ );
+ });
+ return {rows};
+};
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;
diff --git a/src/components/Table/AdminTableHead.stories.tsx b/src/components/Table/AdminTableHead.stories.tsx
index 0b242c4..13c13ff 100644
--- a/src/components/Table/AdminTableHead.stories.tsx
+++ b/src/components/Table/AdminTableHead.stories.tsx
@@ -1,6 +1,6 @@
import type { Meta } from '@storybook/react';
-import { STATION_DETAILS_CATEGORY_LIST } from '@constant';
+import { stationColumns } from '@type';
import AdminTableHead from './AdminTableHead';
@@ -8,10 +8,10 @@ const meta = {
component: AdminTableHead,
tags: ['autodocs'],
args: {
- categoryList: STATION_DETAILS_CATEGORY_LIST,
+ columns: stationColumns,
},
argTypes: {
- categoryList: {
+ columns: {
control: {
type: 'array',
},
@@ -23,5 +23,5 @@ const meta = {
export default meta;
export const Default = () => {
- return ;
+ return ;
};
diff --git a/src/components/Table/AdminTableHead.tsx b/src/components/Table/AdminTableHead.tsx
index 69f0ca1..a1d2461 100644
--- a/src/components/Table/AdminTableHead.tsx
+++ b/src/components/Table/AdminTableHead.tsx
@@ -3,25 +3,25 @@ import TableCell from '@mui/material/TableCell';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
-import type { StationCategoryValues } from '@type';
+import type { ColumnType } from '@type';
-interface Props {
- categoryList: readonly StationCategoryValues[];
+interface TableHeaderProps {
+ columns: Array>;
}
-function AdminTableHead({ categoryList }: Props) {
+const AdminTableHead = ({ columns }: TableHeaderProps) => {
return (
- {categoryList.map((category, index) => (
+ {columns.map((category, index) => (
- {category}
+ {category.header}
))}
);
-}
+};
const tableHeadCss = css`
white-space: pre;
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 383b53c..fb2ba6d 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -14,9 +14,7 @@ export const STATION_DETAILS_CATEGORIES = {
stationState: '충전소 기타 정보',
} as const;
-export const STATION_DETAILS_CATEGORY_LIST = Object.values(STATION_DETAILS_CATEGORIES);
-
-export const ROWS_PER_PAGE = 10;
+export const ROWS_PER_PAGE = 5;
export const LAST_PAGE = 12;
export const MENU_LIST = [
@@ -24,5 +22,4 @@ export const MENU_LIST = [
'충전소 관리',
'충전소 제보 관리',
'충전기 신고 관리',
- '간편 로그인',
] as const;
diff --git a/src/hooks/stations/useFetchStations.ts b/src/hooks/stations/useFetchStations.ts
index f12fcbb..7b7de75 100644
--- a/src/hooks/stations/useFetchStations.ts
+++ b/src/hooks/stations/useFetchStations.ts
@@ -5,16 +5,16 @@ import { useEffect, useState } from 'react';
import { ROWS_PER_PAGE } from '@constant';
import { BASE_URL } from '@constant/url';
-import type { StationProps } from '@type';
+import type { StationDetails } from '@type';
interface StationsResponse {
lastPage: number;
- elements: StationProps[];
+ elements: StationDetails[];
}
export const useFetchStations = (token: string, page: number) => {
const [lastPage, setLastPage] = useState(1);
- const [stationSummaryList, setStationSummaryList] = useState([]);
+ const [stationSummaryList, setStationSummaryList] = useState([]);
const config = {
headers: {
@@ -44,4 +44,4 @@ export const useFetchStations = (token: string, page: number) => {
}, []);
return { lastPage, stationSummaryList };
-};
+};
\ No newline at end of file
diff --git a/src/mocks/index.ts b/src/mocks/index.ts
index 9d2045b..5768922 100644
--- a/src/mocks/index.ts
+++ b/src/mocks/index.ts
@@ -1,6 +1,6 @@
import { ROWS_PER_PAGE } from '../constants';
-const mock = {
+const stationMock = {
stationId: 'HA_1234',
stationName: '충전소',
address: '서울시 강남구 테헤란로 411',
@@ -31,4 +31,44 @@ export const stationEditMock = {
stationState: 'null',
};
-export const elements = Array.from({ length: ROWS_PER_PAGE }, () => mock);
+const misinformationMock = {
+ id: 1,
+ memberId: 2,
+ isChecked: false,
+};
+
+const faultReportMock = {
+ id: 1,
+ memberId: 2,
+ stationId: 3,
+};
+
+const memberMock = {
+ id: 1,
+ email: 'b**ster@gmail.com',
+ role: 'ADMIN',
+};
+
+export const faultReportMockData = Array.from({ length: ROWS_PER_PAGE }, () => faultReportMock);
+export const memberMockData = Array.from({ length: ROWS_PER_PAGE }, () => memberMock);
+
+export const stationMockData = Array.from({ length: ROWS_PER_PAGE }, () => stationMock);
+export const misinformnationMockData = Array.from(
+ { length: ROWS_PER_PAGE },
+ () => misinformationMock
+);
+
+export function getMockData(title: string): Array {
+ switch (title) {
+ case '충전소 관리':
+ return stationMockData as Array;
+ case '충전소 제보 관리':
+ return misinformnationMockData as Array;
+ case '충전기 신고 관리':
+ return faultReportMockData as Array;
+ case '회원 관리':
+ return memberMockData as Array;
+ default:
+ return [];
+ }
+}
diff --git a/src/types/index.ts b/src/types/index.ts
index 9ab7b6c..4778fbf 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,6 +1,74 @@
import type { MENU_LIST, STATION_DETAILS_CATEGORIES } from '@constant';
-export interface StationProps {
+export interface ColumnType {
+ key: K;
+ header: string;
+ width?: number;
+}
+
+interface FaultReportDetails {
+ id: number;
+ stationId: string;
+ memberId: number;
+}
+
+interface MemberDetails {
+ id: number;
+ email: number;
+ role: string;
+}
+
+const memberColumns: ColumnType[] = [
+ {
+ key: 'id',
+ header: 'ID',
+ },
+ {
+ key: 'email',
+ header: 'E-MAIL',
+ },
+ {
+ key: 'role',
+ header: '회원 권한',
+ },
+];
+const faultReportColumns: ColumnType[] = [
+ {
+ key: 'id',
+ header: 'ID',
+ },
+ {
+ key: 'stationId',
+ header: '충전소 ID',
+ },
+ {
+ key: 'memberId',
+ header: '회원 ID',
+ },
+];
+
+type MisinformationDetails = {
+ id: number;
+ memberId: number;
+ isChecked: boolean;
+};
+
+const misinformationColumns: ColumnType[] = [
+ {
+ key: 'id',
+ header: 'ID',
+ },
+ {
+ key: 'memberId',
+ header: '회원 ID',
+ },
+ {
+ key: 'isChecked',
+ header: '확인 여부',
+ },
+];
+
+export interface StationDetails {
stationId: string;
stationName: string;
companyName: string;
@@ -16,6 +84,76 @@ export interface StationProps {
longitude: number;
}
+export const stationColumns: ColumnType[] = [
+ {
+ key: 'stationId',
+ header: 'ID',
+ },
+ {
+ key: 'stationName',
+ header: '충전소 이름',
+ },
+ {
+ key: 'companyName',
+ header: '회사 이름',
+ },
+ {
+ key: 'contact',
+ header: '연락처',
+ },
+ {
+ key: 'detailLocation',
+ header: '상세 위치',
+ },
+ {
+ key: 'isParkingFree',
+ header: '주차 무료',
+ },
+ {
+ key: 'isPrivate',
+ header: '외부인 제한 충전소',
+ },
+ {
+ key: 'operationTime',
+ header: '운영 시간',
+ },
+ {
+ key: 'privateReason',
+ header: '외부인 제한 이유',
+ },
+ {
+ key: 'stationState',
+ header: '충전소 기타 정보',
+ },
+ {
+ key: 'address',
+ header: '주소',
+ },
+ {
+ key: 'latitude',
+ header: '위도',
+ },
+ {
+ key: 'longitude',
+ header: '경도',
+ },
+];
+
+export function getColumnsByTitle(title: string): ColumnType[] {
+ switch (title) {
+ case '충전소 관리':
+ return stationColumns as ColumnType[];
+ case '충전소 제보 관리':
+ return misinformationColumns as ColumnType[];
+ case '충전기 신고 관리':
+ return faultReportColumns as ColumnType[];
+ case '회원 관리':
+ return memberColumns as ColumnType[];
+ default:
+ return [];
+ }
+}
+
export type Menu = (typeof MENU_LIST)[number];
export type StationCategoryKeys = keyof typeof STATION_DETAILS_CATEGORIES;
@@ -24,4 +162,8 @@ export type StationCategoryValues = (typeof STATION_DETAILS_CATEGORIES)[StationC
type ExcludeID = T extends 'ID' ? never : T;
export type StationCategoryValuesWithoutID = ExcludeID;
-export interface StationEditProps extends Omit {}
+export interface StationEditProps extends Omit {}
+
+export interface ModalElementsProps {
+ data: StationDetails[];
+}