fromis_9/frontend-temp/src/App.jsx

147 lines
5.7 KiB
React
Raw Normal View History

import { BrowserRouter, Routes, Route } from "react-router-dom";
import { cn, getTodayKST, formatFullDate } from "@/utils";
import { useAuthStore, useUIStore } from "@/stores";
import { useIsMobile, useCategories, useCalendar } from "@/hooks";
import { memberApi } from "@/api";
import { useQuery } from "@tanstack/react-query";
/**
* 프로미스나인 팬사이트 메인
*
* Phase 5: 커스텀 완료
* - useMediaQuery, useIsMobile, useIsDesktop
* - useScheduleData, useScheduleDetail, useCategories
* - useScheduleSearch (무한 스크롤)
* - useScheduleFiltering, useCategoryCounts
* - useCalendar
* - useAdminAuth
*/
function App() {
const today = getTodayKST();
const isMobile = useIsMobile();
const { isAuthenticated } = useAuthStore();
const { showSuccess, toasts } = useUIStore();
// 커스텀 훅 사용
const { data: categories, isLoading: categoriesLoading } = useCategories();
const calendar = useCalendar();
// 멤버 데이터 (기존 방식 유지)
const { data: members, isLoading: membersLoading } = useQuery({
queryKey: ["members"],
queryFn: memberApi.getMembers,
});
return (
<BrowserRouter>
<Routes>
<Route
path="/"
element={
<div className="min-h-screen flex items-center justify-center bg-gray-50 p-4">
<div className="text-center space-y-4 max-w-md w-full">
<h1 className="text-2xl font-bold text-primary mb-2">
fromis_9 Frontend Refactoring
</h1>
<p className="text-gray-600">Phase 5 완료 - 커스텀 </p>
<p className={cn("text-sm", isMobile ? "text-blue-500" : "text-green-500")}>
디바이스: {isMobile ? "모바일" : "PC"} (useIsMobile )
</p>
<div className="mt-6 p-4 bg-white rounded-lg shadow text-left text-sm space-y-3">
<p><strong>오늘:</strong> {formatFullDate(today)}</p>
<p><strong>인증:</strong> {isAuthenticated ? "✅" : "❌"}</p>
<div className="border-t pt-3">
<p className="font-semibold mb-2">useCategories </p>
<p>
{categoriesLoading ? "로딩 중..." : `${categories?.length || 0}개 카테고리`}
</p>
{categories && (
<div className="flex flex-wrap gap-1 mt-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">useCalendar </p>
<p><strong>현재:</strong> {calendar.year} {calendar.monthName}</p>
<p><strong>선택:</strong> {calendar.selectedDate}</p>
<div className="flex gap-2 mt-2">
<button
onClick={calendar.goToPrevMonth}
disabled={!calendar.canGoPrevMonth}
className={cn(
"px-3 py-1 rounded text-xs",
calendar.canGoPrevMonth ? "bg-primary text-white" : "bg-gray-200 text-gray-400"
)}
>
이전
</button>
<button
onClick={calendar.goToToday}
className="px-3 py-1 bg-gray-500 text-white rounded text-xs"
>
오늘
</button>
<button
onClick={calendar.goToNextMonth}
className="px-3 py-1 bg-primary text-white rounded text-xs"
>
다음
</button>
</div>
</div>
<div className="border-t pt-3">
<p className="font-semibold mb-2">멤버 데이터</p>
<p>{membersLoading ? "로딩 중..." : `${members?.length || 0}`}</p>
{members && (
<div className="flex flex-wrap gap-1 mt-1">
{members.map((m) => (
<span key={m.id} className="px-2 py-0.5 bg-gray-100 rounded text-xs">
{m.name}
</span>
))}
</div>
)}
</div>
</div>
</div>
{/* 토스트 표시 */}
<div className="fixed bottom-4 right-4 space-y-2">
{toasts.map((toast) => (
<div
key={toast.id}
className={cn(
"px-4 py-2 rounded shadow-lg text-white text-sm",
toast.type === "success" && "bg-green-500",
toast.type === "error" && "bg-red-500",
toast.type === "warning" && "bg-yellow-500",
toast.type === "info" && "bg-blue-500"
)}
>
{toast.message}
</div>
))}
</div>
</div>
}
/>
</Routes>
</BrowserRouter>
);
}
export default App;