fromis_9/frontend-temp/src/App.jsx

197 lines
6.3 KiB
React
Raw Normal View History

import { BrowserRouter, Routes, Route, NavLink } from "react-router-dom";
import { cn, getTodayKST, formatFullDate } from "@/utils";
import { useUIStore } from "@/stores";
import { useIsMobile, useCategories, useScheduleData } from "@/hooks";
import { ErrorBoundary, Loading, ToastContainer, ScheduleCard, Layout } from "@/components";
import { Schedule, Album } from "@/pages";
/**
* 페이지 (임시)
*/
function Home() {
const today = getTodayKST();
const isMobile = useIsMobile();
const { showSuccess, showError } = useUIStore();
const { data: categories, isLoading: categoriesLoading } = useCategories();
const currentDate = new Date();
const { data: schedules, isLoading: schedulesLoading } = useScheduleData(
currentDate.getFullYear(),
currentDate.getMonth() + 1
);
return (
<div className={cn("p-4", isMobile ? "pb-20" : "")}>
<div className="max-w-2xl mx-auto space-y-4">
<div className="text-center">
<h1 className="text-2xl font-bold text-primary mb-2">
fromis_9 Frontend Refactoring
</h1>
<p className="text-gray-600">Phase 7 진행 - 스케줄 페이지</p>
<p className={cn("text-sm", isMobile ? "text-blue-500" : "text-green-500")}>
디바이스: {isMobile ? "모바일" : "PC"}
</p>
</div>
<div className="p-4 bg-white rounded-lg shadow text-sm space-y-3">
<p><strong>오늘:</strong> {formatFullDate(today)}</p>
<div className="border-t pt-3">
<p className="font-semibold mb-2">카테고리 ({categories?.length || 0})</p>
{categoriesLoading ? (
<Loading size="sm" />
) : (
<div className="flex flex-wrap gap-1">
{categories?.map((c) => (
<span
key={c.id}
className="px-2 py-0.5 rounded text-xs text-white"
style={{ backgroundColor: c.color }}
>
{c.name}
</span>
))}
</div>
)}
</div>
<div className="border-t pt-3">
<p className="font-semibold mb-2">토스트 테스트</p>
<div className="flex gap-2">
<button
onClick={() => showSuccess("성공 메시지!")}
className="px-3 py-1 bg-emerald-500 text-white rounded text-xs"
>
성공
</button>
<button
onClick={() => showError("에러 메시지!")}
className="px-3 py-1 bg-red-500 text-white rounded text-xs"
>
에러
</button>
</div>
</div>
<div className="border-t pt-3">
<p className="font-semibold mb-2">페이지 이동</p>
<div className="flex gap-2">
<NavLink
to="/schedule"
className="px-3 py-1 bg-primary text-white rounded text-xs"
>
일정 페이지
</NavLink>
</div>
</div>
</div>
{/* ScheduleCard 컴포넌트 테스트 */}
{schedulesLoading ? (
<div className="p-4 bg-white rounded-lg shadow">
<Loading size="sm" text="스케줄 로딩 중..." />
</div>
) : schedules?.length > 0 ? (
<>
{/* Public Variant (공개 페이지용) */}
<div className="p-4 bg-white rounded-lg shadow">
<p className="font-semibold mb-3 text-sm">variant="public" (공개 페이지용)</p>
<div className="space-y-3">
{schedules.slice(0, 2).map((schedule) => (
<ScheduleCard
key={schedule.id}
schedule={schedule}
variant="public"
onClick={() => showSuccess(`${schedule.title} 클릭`)}
/>
))}
</div>
</div>
{/* Admin Variant (관리자 페이지용) */}
<div className="p-4 bg-white rounded-lg shadow">
<p className="font-semibold mb-3 text-sm">variant="admin" (관리자 페이지용)</p>
<div className="divide-y">
{schedules.slice(0, 2).map((schedule) => (
<ScheduleCard
key={schedule.id}
schedule={schedule}
variant="admin"
onClick={() => showSuccess(`${schedule.title} 클릭`)}
onEdit={(s) => showSuccess(`${s.title} 수정`)}
onDelete={(s) => showError(`${s.title} 삭제`)}
/>
))}
</div>
</div>
</>
) : (
<div className="p-4 bg-white rounded-lg shadow">
<p className="text-gray-500 text-sm">이번 스케줄이 없습니다.</p>
</div>
)}
</div>
</div>
);
}
/**
* 프로미스나인 팬사이트 메인
*
* Phase 8: 앨범 페이지 마이그레이션
* - Album 페이지 (PC/Mobile 통합)
* - useAlbums 추가
*/
function App() {
return (
<BrowserRouter>
<ErrorBoundary>
<Routes>
{/* 홈 */}
<Route
path="/"
element={
<Layout>
<Home />
<ToastContainer />
</Layout>
}
/>
{/* 스케줄 */}
<Route
path="/schedule"
element={
<Layout useCustomLayout>
<Schedule />
<ToastContainer />
</Layout>
}
/>
{/* 임시 페이지들 */}
<Route
path="/members"
element={
<Layout pageTitle="멤버">
<div className="p-4 text-center text-gray-500">멤버 페이지 (준비 )</div>
</Layout>
}
/>
{/* 앨범 */}
<Route
path="/album"
element={
<Layout pageTitle="앨범">
<Album />
<ToastContainer />
</Layout>
}
/>
</Routes>
</ErrorBoundary>
</BrowserRouter>
);
}
export default App;