You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
joint_exc/frontend/src/App.tsx

129 lines
4.0 KiB

/**
* アプリケーションのルートコンポーネント
* ルーティング設定、テーマ設定、認証保護などの基本構成を提供する
*/
import React from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { ThemeProvider, createTheme, CssBaseline, Box } from '@mui/material';
import Layout from './components/Layout';
import LoginPage from './pages/LoginPage';
import RegisterPage from './pages/RegisterPage';
import TaskListPage from './pages/TaskListPage';
import StockPage from './pages/StockPage';
import './App.css';
/**
* アプリケーション全体のMaterial UIテーマを定義
* カラーパレット、タイポグラフィ、コンポーネントのスタイルオーバーライドを設定
*/
const theme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#1976d2',
},
secondary: {
main: '#dc004e',
},
background: {
default: '#f5f5f5',
paper: '#ffffff',
},
},
typography: {
fontFamily: [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
].join(','),
},
components: {
MuiPaper: {
styleOverrides: {
root: {
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)',
},
},
},
},
});
/**
* 認証が必要なルートを保護するためのコンポーネント
* ローカルストレージにトークンがない場合はログインページにリダイレクト
* トークンがある場合は子コンポーネントをレンダリング
*/
const PrivateRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const token = localStorage.getItem('token');
if (!token) {
return <Navigate to="/login" replace />;
}
return <>{children}</>;
};
/**
* アプリケーションのメインコンポーネント
* ルーティング構造を定義し、適切なページコンポーネントを表示
* - 未認証ユーザー: ログイン/登録ページにアクセス可能
* - 認証済みユーザー: タスク一覧ページにアクセス可能
* - ルートパスへのアクセスは自動的にタスク一覧にリダイレクト
*/
const App: React.FC = () => {
return (
<ThemeProvider theme={theme}>
<CssBaseline /> {/* MUIのリセットCSSを適用 */}
<Box className="app">
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route path="/" element={<Layout />}>
{/* ルートパスへのアクセスはタスク一覧にリダイレクト */}
<Route index element={<Navigate to="/tasks" replace />} />
{/* タスク一覧は認証が必要なため、PrivateRouteでラップ */}
<Route
path="tasks"
element={
<PrivateRoute>
<TaskListPage />
</PrivateRoute>
}
/>
</Route>
<Route path="/" element={<Layout />}>
{/* ルートパスへのアクセスはタスク一覧にリダイレクト */}
<Route index element={<Navigate to="/stock" replace />} />
{/* タスク一覧は認証が必要なため、PrivateRouteでラップ */}
<Route
path="stock"
element={
<PrivateRoute>
<StockPage />
</PrivateRoute>
}
/>
{/* テストページへのルートを追加 */}
<Route
path="stock"
element={
<PrivateRoute>
<StockPage />
</PrivateRoute>
}
/>
</Route>
</Routes>
</BrowserRouter>
</Box>
</ThemeProvider>
);
};
export default App;