|
|
|
@ -38,27 +38,50 @@ const Layout: React.FC = () => { |
|
|
|
|
const navigate = useNavigate(); |
|
|
|
|
const location = useLocation(); |
|
|
|
|
const [drawerOpen, setDrawerOpen] = useState(false); |
|
|
|
|
const [bottomNavi, setBottomNavi] = useState(1); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* ログアウト処理を行うハンドラー関数 |
|
|
|
|
* ローカルストレージからトークンを削除し、ログインページにリダイレクト |
|
|
|
|
*/ |
|
|
|
|
const handleLogout = () => { |
|
|
|
|
localStorage.removeItem('token'); |
|
|
|
|
navigate('/login'); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getTabIndex = (pathname: string) => { |
|
|
|
|
switch (pathname) { |
|
|
|
|
case '/stock': |
|
|
|
|
return 0; |
|
|
|
|
case '/tasks': |
|
|
|
|
return 1; |
|
|
|
|
case '/recipeList': |
|
|
|
|
return 2; |
|
|
|
|
default: |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const [bottomNavi, setBottomNavi] = useState(getTabIndex(location.pathname)); |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
setBottomNavi(getTabIndex(location.pathname)); |
|
|
|
|
}, [location.pathname]); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* ログアウト処理を行うハンドラー関数 |
|
|
|
|
* ローカルストレージからトークンを削除し、ログインページにリダイレクト |
|
|
|
|
*/ |
|
|
|
|
const handleLogout = () => { |
|
|
|
|
localStorage.removeItem('token'); |
|
|
|
|
navigate('/login'); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// メニューを開閉するハンドラー
|
|
|
|
|
const toggleDrawer = () => { |
|
|
|
|
setDrawerOpen(!drawerOpen); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// メッセージ表示
|
|
|
|
|
|
|
|
|
|
// メニューを開閉するハンドラー
|
|
|
|
|
const toggleDrawer = () => { |
|
|
|
|
setDrawerOpen(!drawerOpen); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// メッセージ表示
|
|
|
|
|
|
|
|
|
|
// ページ遷移後もメッセージを維持
|
|
|
|
|
useEffect(() => { |
|
|
|
@ -91,67 +114,57 @@ const Layout: React.FC = () => { |
|
|
|
|
sessionStorage.removeItem('globalMessage'); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handleBottomNavigation = (event: React.SyntheticEvent, newValue: any) => { |
|
|
|
|
setBottomNavi(newValue); |
|
|
|
|
switch(newValue) { |
|
|
|
|
case 0: |
|
|
|
|
navigate('stock'); |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
navigate('tasks'); |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
navigate('recipeList'); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// ここでルーティング処理などを行う
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}> |
|
|
|
|
{/* ヘッダー部分 - アプリ名とログアウトボタンを表示 */} |
|
|
|
|
<AppBar position="static" elevation={0}> |
|
|
|
|
<Toolbar> |
|
|
|
|
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> |
|
|
|
|
shopchop |
|
|
|
|
</Typography> |
|
|
|
|
<Button color="inherit" onClick={handleLogout}> |
|
|
|
|
ログアウト |
|
|
|
|
</Button> |
|
|
|
|
</Toolbar> |
|
|
|
|
</AppBar> |
|
|
|
|
|
|
|
|
|
<Paper sx={{ position: 'fixed', bottom: 0, left: 0, right: 0 }} elevation={3}> |
|
|
|
|
<BottomNavigation |
|
|
|
|
showLabels |
|
|
|
|
value={bottomNavi} |
|
|
|
|
onChange={(event, newValue) => { |
|
|
|
|
setBottomNavi(newValue); |
|
|
|
|
switch(newValue) { |
|
|
|
|
case 0: |
|
|
|
|
navigate('stock'); |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
navigate('tasks'); |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
navigate('recipeList'); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// ここでルーティング処理などを行う
|
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
<BottomNavigationAction label="在庫" icon={<InventoryIcon />} /> |
|
|
|
|
<BottomNavigationAction label="買うもの" icon={<ShoppingCartIcon />} /> |
|
|
|
|
<BottomNavigationAction label="レシピ" icon={<SoupKitchenIcon />} /> |
|
|
|
|
</BottomNavigation> |
|
|
|
|
</Paper> |
|
|
|
|
|
|
|
|
|
{/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */} |
|
|
|
|
<Box component="main" sx={{ flexGrow: 1, bgcolor: 'background.default', py: 3 }}> |
|
|
|
|
<Container> |
|
|
|
|
|
|
|
|
|
<MessageContext.Provider value={{ showErrorMessage, showWarningMessage, showSuccessMessage, showInfoMessage }}> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}> |
|
|
|
|
{/* ヘッダー部分 - アプリ名とログアウトボタンを表示 */} |
|
|
|
|
<AppBar position="static" elevation={0}> |
|
|
|
|
<Toolbar> |
|
|
|
|
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> |
|
|
|
|
shopchop |
|
|
|
|
</Typography> |
|
|
|
|
<Button color="inherit" onClick={handleLogout}> |
|
|
|
|
ログアウト |
|
|
|
|
</Button> |
|
|
|
|
</Toolbar> |
|
|
|
|
</AppBar> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Paper sx={{ position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: (theme) => theme.zIndex.drawer + 1 }} elevation={3}> |
|
|
|
|
<BottomNavigation |
|
|
|
|
showLabels |
|
|
|
|
value={bottomNavi} |
|
|
|
|
onChange={(event, newValue) => { |
|
|
|
|
setBottomNavi(newValue); |
|
|
|
|
switch (newValue) { |
|
|
|
|
case 0: |
|
|
|
|
navigate('stock'); |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
navigate('tasks'); |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
navigate('recipeList'); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// ここでルーティング処理などを行う
|
|
|
|
|
}} |
|
|
|
|
> |
|
|
|
|
<BottomNavigationAction label="在庫" icon={<InventoryIcon />} /> |
|
|
|
|
<BottomNavigationAction label="買うもの" icon={<ShoppingCartIcon />} /> |
|
|
|
|
<BottomNavigationAction label="レシピ" icon={<SoupKitchenIcon />} /> |
|
|
|
|
</BottomNavigation> |
|
|
|
|
</Paper> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */} |
|
|
|
|
<Box component="main" sx={{ flexGrow: 1, bgcolor: 'background.default', py: 3 }}> |
|
|
|
|
<Container> |
|
|
|
|
<MessageContext.Provider value={{ showErrorMessage, showWarningMessage, showSuccessMessage, showInfoMessage }}> |
|
|
|
|
<MessageAlert |
|
|
|
|
open={msgOpen} |
|
|
|
|
message={msgText} |
|
|
|
@ -160,11 +173,11 @@ const Layout: React.FC = () => { |
|
|
|
|
/> |
|
|
|
|
<Outlet /> {/* React Router の Outlet - 子ルートのコンポーネントがここにレンダリングされる */} |
|
|
|
|
</MessageContext.Provider> |
|
|
|
|
|
|
|
|
|
</Container> |
|
|
|
|
</Container> |
|
|
|
|
</Box> |
|
|
|
|
</Box> |
|
|
|
|
</Box> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default Layout; |
|
|
|
|
export default Layout; |
|
|
|
|