minecraft-web/frontend/src/App.jsx

107 lines
4.5 KiB
JavaScript

import React, { useEffect } from 'react';
import { Routes, Route, useLocation } from 'react-router-dom';
import { AnimatePresence, motion } from 'framer-motion';
import DeviceLayout, { useIsMobile } from './components/DeviceLayout';
import Sidebar from './components/Sidebar';
import ServerDetail from './pages/ServerDetail';
import WorldsPage from './pages/WorldsPage';
import PlayersPage from './pages/PlayersPage';
import PlayerStatsPage from './pages/PlayerStatsPage';
import WorldMapPage from './pages/WorldMapPage';
import LoginPage from './pages/LoginPage';
import RegisterPage from './pages/RegisterPage';
import VerifyEmailPage from './pages/VerifyEmailPage';
import Admin from './pages/Admin';
import ProfilePage from './pages/ProfilePage';
// 페이지 전환 애니메이션 래퍼 컴포넌트
const PageWrapper = ({ children }) => (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
>
{children}
</motion.div>
);
function App() {
const isMobile = useIsMobile();
const location = useLocation();
// 인증 페이지 여부 확인 (사이드바 없이 렌더링)
const isAuthPage = ['/login', '/register'].includes(location.pathname) ||
location.pathname.startsWith('/verify/');
// 별도 레이아웃 페이지 (관리자, 프로필)
const isStandalonePage = ['/admin', '/profile'].includes(location.pathname);
// 라우트 전환 시 스크롤 맨 위로
useEffect(() => {
window.scrollTo(0, 0);
}, [location.pathname]);
// 인증 페이지는 사이드바 없이 렌더링
if (isAuthPage) {
return (
<DeviceLayout>
<div className="min-h-screen bg-mc-bg text-gray-200 font-sans selection:bg-mc-green/30">
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-[0.03] pointer-events-none"></div>
<AnimatePresence mode="wait">
<Routes location={location} key={location.pathname}>
<Route path="/login" element={<PageWrapper><LoginPage /></PageWrapper>} />
<Route path="/register" element={<PageWrapper><RegisterPage /></PageWrapper>} />
<Route path="/verify/:token" element={<PageWrapper><VerifyEmailPage /></PageWrapper>} />
</Routes>
</AnimatePresence>
</div>
</DeviceLayout>
);
}
// 관리자/프로필 페이지는 별도 레이아웃
if (isStandalonePage) {
return (
<DeviceLayout>
<div className="bg-mc-bg text-gray-200 font-sans selection:bg-mc-green/30">
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-[0.03] pointer-events-none"></div>
<AnimatePresence mode="wait">
<Routes location={location} key={location.pathname}>
<Route path="/admin" element={<PageWrapper><Admin /></PageWrapper>} />
<Route path="/profile" element={<PageWrapper><ProfilePage /></PageWrapper>} />
</Routes>
</AnimatePresence>
</div>
</DeviceLayout>
);
}
return (
<DeviceLayout>
<div className="min-h-screen bg-mc-bg text-gray-200 font-sans selection:bg-mc-green/30">
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-[0.03] pointer-events-none"></div>
{/* 사이드바 + 메인 콘텐츠 레이아웃 */}
<div className={`flex min-h-screen ${isMobile ? 'flex-col' : ''}`}>
<Sidebar isMobile={isMobile} />
{/* 메인 콘텐츠 영역 */}
<main className="flex-1 min-w-0 overflow-hidden">
<AnimatePresence mode="wait">
<Routes location={location} key={location.pathname}>
<Route path="/" element={<PageWrapper><ServerDetail isMobile={isMobile} /></PageWrapper>} />
<Route path="/worlds" element={<PageWrapper><WorldsPage isMobile={isMobile} /></PageWrapper>} />
<Route path="/players" element={<PageWrapper><PlayersPage isMobile={isMobile} /></PageWrapper>} />
<Route path="/player/:uuid/stats" element={<PageWrapper><PlayerStatsPage isMobile={isMobile} /></PageWrapper>} />
<Route path="/worldmap" element={<PageWrapper><WorldMapPage isMobile={isMobile} /></PageWrapper>} />
</Routes>
</AnimatePresence>
</main>
</div>
</div>
</DeviceLayout>
);
}
export default App;