fix: BudgetProvider 및 isMobile 오류 수정

- App.tsx에 BudgetProvider 추가로 지출 페이지 오류 해결
- SummaryCards 컴포넌트에 useIsMobile 훅 import 추가로 분석 페이지 오류 해결
- 모든 페이지가 정상적으로 작동하도록 수정

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
hansoo
2025-07-14 14:25:49 +09:00
parent 3934ab933f
commit 3225d0492b
2 changed files with 69 additions and 64 deletions

View File

@@ -37,6 +37,7 @@ import {
ClerkProvider, ClerkProvider,
ClerkDebugInfo, ClerkDebugInfo,
} from "./components/providers/ClerkProvider"; } from "./components/providers/ClerkProvider";
import { BudgetProvider } from "./contexts/budget/BudgetContext";
// 페이지 컴포넌트들을 개선된 레이지 로딩으로 변경 (ChunkLoadError 재시도 포함) // 페이지 컴포넌트들을 개선된 레이지 로딩으로 변경 (ChunkLoadError 재시도 포함)
const Index = createLazyComponent(() => import("./pages/Index")); const Index = createLazyComponent(() => import("./pages/Index"));
@@ -380,77 +381,79 @@ function App() {
fallback={<ErrorScreen error={error} retry={handleRetry} />} fallback={<ErrorScreen error={error} retry={handleRetry} />}
showDialog={false} showDialog={false}
> >
<BasicLayout> <BudgetProvider>
<PageTracker /> <BasicLayout>
<Suspense fallback={<PageLoadingSpinner />}> <PageTracker />
<Routes> <Suspense fallback={<PageLoadingSpinner />}>
<Route path="/" element={<Index />} /> <Routes>
{/* Clerk 라우트 다시 활성화 */} <Route path="/" element={<Index />} />
<Route path="/sign-in/*" element={<SignIn />} /> {/* Clerk 라우트 다시 활성화 */}
<Route path="/sign-up/*" element={<SignUp />} /> <Route path="/sign-in/*" element={<SignIn />} />
<Route path="/login" element={<Login />} /> <Route path="/sign-up/*" element={<SignUp />} />
<Route path="/register" element={<Register />} /> <Route path="/login" element={<Login />} />
<Route path="/settings" element={<Settings />} /> <Route path="/register" element={<Register />} />
<Route path="/transactions" element={<Transactions />} /> <Route path="/settings" element={<Settings />} />
<Route path="/analytics" element={<Analytics />} /> <Route path="/transactions" element={<Transactions />} />
<Route path="/profile" element={<ProfileManagement />} /> <Route path="/analytics" element={<Analytics />} />
<Route path="/payment-methods" element={<PaymentMethods />} /> <Route path="/profile" element={<ProfileManagement />} />
<Route path="/help-support" element={<HelpSupport />} /> <Route path="/payment-methods" element={<PaymentMethods />} />
<Route <Route path="/help-support" element={<HelpSupport />} />
path="/security-privacy" <Route
element={<SecurityPrivacySettings />} path="/security-privacy"
element={<SecurityPrivacySettings />}
/>
<Route
path="/notifications"
element={<NotificationSettings />}
/>
<Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/pwa-debug" element={<PWADebugPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
</Suspense>
{/* React Query 캐시 관리 */}
<Suspense fallback={null}>
<QueryCacheManager
cleanupIntervalMinutes={30}
enableOfflineCache={true}
enableCacheAnalysis={isDevMode}
/> />
<Route </Suspense>
path="/notifications"
element={<NotificationSettings />} {/* 오프라인 상태 관리 */}
<Suspense fallback={null}>
<OfflineManager
showOfflineToast={true}
autoSyncOnReconnect={true}
/> />
<Route path="/forgot-password" element={<ForgotPassword />} /> </Suspense>
<Route path="/pwa-debug" element={<PWADebugPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
</Suspense>
{/* React Query 캐시 관리 */}
<Suspense fallback={null}>
<QueryCacheManager
cleanupIntervalMinutes={30}
enableOfflineCache={true}
enableCacheAnalysis={isDevMode}
/>
</Suspense>
{/* 오프라인 상태 관리 */} {/* 백그라운드 자동 동기화 - 성능 최적화로 30초 간격으로 조정 */}
<Suspense fallback={null}> <Suspense fallback={null}>
<OfflineManager <BackgroundSync
showOfflineToast={true} intervalMinutes={0.5}
autoSyncOnReconnect={true} syncOnFocus={true}
/> syncOnOnline={true}
</Suspense> />
</Suspense>
{/* 백그라운드 자동 동기화 - 성능 최적화로 30초 간격으로 조정 */} {/* 개발환경에서 Sentry 테스트 버튼 */}
<Suspense fallback={null}> <Suspense fallback={null}>
<BackgroundSync <SentryTestButton />
intervalMinutes={0.5} </Suspense>
syncOnFocus={true}
syncOnOnline={true}
/>
</Suspense>
{/* 개발환경에서 Sentry 테스트 버튼 */} {/* 개발환경에서 Clerk 상태 디버깅 */}
<Suspense fallback={null}> <ClerkDebugInfo />
<SentryTestButton />
</Suspense>
{/* 개발환경에서 Clerk 상태 디버깅 */} {/* 개발환경에서 환경 변수 테스트 */}
<ClerkDebugInfo /> {isDevMode && <EnvTest />}
{/* 개발환경에서 환경 변수 테스트 */} {/* Clerk 디버그 및 제어 */}
{isDevMode && <EnvTest />} <Suspense fallback={null}>
<ClerkDebugControl />
{/* Clerk 디버그 및 제어 */} </Suspense>
<Suspense fallback={null}> </BasicLayout>
<ClerkDebugControl /> </BudgetProvider>
</Suspense>
</BasicLayout>
{isDevMode && <ReactQueryDevtools initialIsOpen={false} />} {isDevMode && <ReactQueryDevtools initialIsOpen={false} />}
</SentryErrorBoundary> </SentryErrorBoundary>
</QueryClientProvider> </QueryClientProvider>

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { Wallet, CreditCard, Coins } from "lucide-react"; import { Wallet, CreditCard, Coins } from "lucide-react";
import { formatCurrency } from "@/utils/currencyFormatter"; import { formatCurrency } from "@/utils/currencyFormatter";
import { useIsMobile } from "@/hooks/use-mobile";
interface SummaryCardsProps { interface SummaryCardsProps {
totalBudget: number; totalBudget: number;
totalExpense: number; totalExpense: number;
@@ -11,6 +12,7 @@ const SummaryCards: React.FC<SummaryCardsProps> = ({
totalExpense, totalExpense,
_savingsPercentage, _savingsPercentage,
}) => { }) => {
const isMobile = useIsMobile();
// 남은 예산 계산 // 남은 예산 계산
const remainingBudget = totalBudget - totalExpense; const remainingBudget = totalBudget - totalExpense;
const isOverBudget = remainingBudget < 0; const isOverBudget = remainingBudget < 0;