diff --git a/client/package-lock.json b/client/package-lock.json index 8b8d05ea..db4b820f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -55,6 +55,7 @@ "react-day-picker": "9.7.0", "react-dom": "^19.1.0", "react-dropzone": "^14.3.8", + "react-error-boundary": "^6.0.0", "react-hook-form": "^7.58.1", "react-hotkeys-hook": "^4.6.2", "react-i18next": "^15.5.3", @@ -7411,6 +7412,18 @@ "react": ">= 16.8 || 18.0.0" } }, + "node_modules/react-error-boundary": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.0.0.tgz", + "integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-hook-form": { "version": "7.60.0", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", diff --git a/client/package.json b/client/package.json index 7bf5f422..b2fb0fcf 100644 --- a/client/package.json +++ b/client/package.json @@ -69,6 +69,7 @@ "react-day-picker": "9.7.0", "react-dom": "^19.1.0", "react-dropzone": "^14.3.8", + "react-error-boundary": "^6.0.0", "react-hook-form": "^7.58.1", "react-hotkeys-hook": "^4.6.2", "react-i18next": "^15.5.3", diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index d5ceb650..fd0c9844 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -149,6 +149,9 @@ importers: react-dropzone: specifier: ^14.3.8 version: 14.3.8(react@19.1.0) + react-error-boundary: + specifier: ^6.0.0 + version: 6.0.0(react@19.1.0) react-hook-form: specifier: ^7.58.1 version: 7.58.1(react@19.1.0) @@ -2818,6 +2821,11 @@ packages: peerDependencies: react: '>= 16.8 || 18.0.0' + react-error-boundary@6.0.0: + resolution: {integrity: sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==} + peerDependencies: + react: '>=16.13.1' + react-hook-form@7.58.1: resolution: {integrity: sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==} engines: {node: '>=18.0.0'} @@ -5894,6 +5902,11 @@ snapshots: prop-types: 15.8.1 react: 19.1.0 + react-error-boundary@6.0.0(react@19.1.0): + dependencies: + '@babel/runtime': 7.27.6 + react: 19.1.0 + react-hook-form@7.58.1(react@19.1.0): dependencies: react: 19.1.0 diff --git a/client/src/core/components/error-boundary/component-error-fallback.tsx b/client/src/core/components/error-boundary/component-error-fallback.tsx new file mode 100644 index 00000000..88befebd --- /dev/null +++ b/client/src/core/components/error-boundary/component-error-fallback.tsx @@ -0,0 +1,52 @@ +import { Button } from "@/core/components/ui/button"; +import { AlertCircle, RefreshCw } from "lucide-react"; + +interface ComponentErrorFallbackProps { + error: Error; + resetErrorBoundary: () => void; + componentName?: string; +} + +export function ComponentErrorFallback({ + error, + resetErrorBoundary, + componentName = "Component" +}: ComponentErrorFallbackProps) { + return ( +
+
+
+ +
+ +

+ {componentName} Error +

+ +

+ This component failed to load. Try refreshing or contact support if the issue persists. +

+ + + + {process.env.NODE_ENV === 'development' && ( +
+ + Error details + +
+              {error.message}
+            
+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/client/src/core/components/error-boundary/error-fallback.tsx b/client/src/core/components/error-boundary/error-fallback.tsx new file mode 100644 index 00000000..a3a44469 --- /dev/null +++ b/client/src/core/components/error-boundary/error-fallback.tsx @@ -0,0 +1,48 @@ +import { Button } from "@/core/components/ui/button"; +import { AlertTriangle, RefreshCw } from "lucide-react"; + +interface ErrorFallbackProps { + error: Error; + resetErrorBoundary: () => void; +} + +export function ErrorFallback({ error, resetErrorBoundary }: ErrorFallbackProps) { + return ( +
+
+
+
+ +
+
+ +

+ Something went wrong +

+ +

+ We encountered an unexpected error. Please try refreshing the page or contact support if the problem persists. +

+ +
+ + +
+ + Show error details + +
+              {error.message}
+            
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/client/src/core/components/error-boundary/index.tsx b/client/src/core/components/error-boundary/index.tsx new file mode 100644 index 00000000..2ca398d8 --- /dev/null +++ b/client/src/core/components/error-boundary/index.tsx @@ -0,0 +1,24 @@ +import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary'; +import { ErrorInfo } from 'react'; +import { ErrorFallback } from './error-fallback'; +import { RouteErrorFallback } from './route-error-fallback'; +import { ComponentErrorFallback } from './component-error-fallback'; + +interface ErrorBoundaryProps { + children: React.ReactNode; + fallback?: React.ComponentType<{ error: Error; resetErrorBoundary: () => void }>; + onError?: (error: Error, info: ErrorInfo) => void; +} + +export function ErrorBoundary({ children, fallback, onError }: ErrorBoundaryProps) { + return ( + + {children} + + ); +} + +export { ErrorFallback, RouteErrorFallback, ComponentErrorFallback }; \ No newline at end of file diff --git a/client/src/core/components/error-boundary/route-error-fallback.tsx b/client/src/core/components/error-boundary/route-error-fallback.tsx new file mode 100644 index 00000000..a213806b --- /dev/null +++ b/client/src/core/components/error-boundary/route-error-fallback.tsx @@ -0,0 +1,68 @@ +import { Button } from "@/core/components/ui/button"; +import { AlertTriangle, Home, RefreshCw } from "lucide-react"; +import { useNavigate } from "@tanstack/react-router"; + +interface RouteErrorFallbackProps { + error: Error; + resetErrorBoundary: () => void; +} + +export function RouteErrorFallback({ error, resetErrorBoundary }: RouteErrorFallbackProps) { + const navigate = useNavigate(); + + const handleGoHome = () => { + navigate({ to: "/dashboard/home" }); + resetErrorBoundary(); + }; + + return ( +
+
+
+
+ +
+
+ +

+ Page Error +

+ +

+ This page encountered an error and couldn't be loaded. You can try refreshing the page or returning to the dashboard. +

+ +
+ + + +
+ +
+ + Show technical details + +
+
+ {error.name}: {error.message} +
+ {error.stack && ( +
+                {error.stack}
+              
+ )} +
+
+
+
+ ); +} \ No newline at end of file diff --git a/client/src/core/components/loading/index.tsx b/client/src/core/components/loading/index.tsx new file mode 100644 index 00000000..78b7b5bb --- /dev/null +++ b/client/src/core/components/loading/index.tsx @@ -0,0 +1,123 @@ +import { Skeleton } from "@/core/components/ui/skeleton"; +import { Spinner } from "@/core/components/ui/spinner"; + +// Page level loading component +export function PageLoader() { + return ( +
+
+ +

Loading...

+
+
+ ); +} + +// Table loading skeleton +export function TableLoader() { + return ( +
+
+ + +
+
+ {Array.from({ length: 8 }).map((_, i) => ( +
+ +
+ + +
+ +
+ ))} +
+
+ ); +} + +// Form loading skeleton +export function FormLoader() { + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ ); +} + +// Card loading skeleton +export function CardLoader() { + return ( +
+
+ + +
+ +
+ + +
+
+ ); +} + +// Dashboard grid loader +export function DashboardLoader() { + return ( +
+
+ + +
+
+ {Array.from({ length: 6 }).map((_, i) => ( + + ))} +
+
+ ); +} + +// Inline component loader +export function InlineLoader({ text = "Loading..." }: { text?: string }) { + return ( +
+
+ {text} +
+ ); +} + +// Sidebar loader +export function SidebarLoader() { + return ( +
+ +
+ {Array.from({ length: 5 }).map((_, i) => ( +
+ + +
+ ))} +
+
+ ); +} \ No newline at end of file diff --git a/client/src/main.tsx b/client/src/main.tsx index a60f06dc..b098333e 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -3,6 +3,7 @@ import ReactDOM from "react-dom/client"; import { StrictMode } from "react"; import { App } from "./app"; import "./core/i18n/config.ts" +import { PageLoader } from "@/core/components/loading"; import "./index.css"; @@ -11,7 +12,7 @@ if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement); root.render( - Loading...
}> + }> diff --git a/client/src/routes/__root.tsx b/client/src/routes/__root.tsx index 0212ef61..ae00d265 100644 --- a/client/src/routes/__root.tsx +++ b/client/src/routes/__root.tsx @@ -6,6 +6,7 @@ import { ThemeProvider } from "@/features/preferences/contexts/theme.provider"; import type { QueryClient } from "@tanstack/react-query"; import { AuthInterceptor } from "@/features/auth/components/auth-interceptor"; import { PreferencesProvider } from "@/features/preferences/components/preferences-provider"; +import { ErrorBoundary, RouteErrorFallback } from "@/core/components/error-boundary"; interface RouterContext { queryClient: QueryClient; @@ -20,7 +21,7 @@ export const Route = createRootRouteWithContext()({ function RootComponent() { return ( - <> + @@ -31,6 +32,6 @@ function RootComponent() { - + ); } diff --git a/client/src/routes/dashboard/accounts.tsx b/client/src/routes/dashboard/accounts.tsx index 00f8750a..0a5fef27 100644 --- a/client/src/routes/dashboard/accounts.tsx +++ b/client/src/routes/dashboard/accounts.tsx @@ -1,5 +1,6 @@ import { createFileRoute, useRouteContext } from "@tanstack/react-router"; import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query"; +import { Suspense } from "react"; import { accountService } from "@/features/accounts/services/account"; import { DraggableAccountGroups } from "@/features/accounts/components/account"; @@ -14,6 +15,7 @@ import { groupAccountsByType } from "@/features/accounts/components/account.util import { SidebarTrigger } from "@/core/components/ui/sidebar"; import { getAllAccountsWithTrends } from "@/features/accounts/services/account.queries"; import { EmptyStateGuide } from "@/core/components/EmptyStateGuide"; +import { ErrorBoundary } from "@/core/components/error-boundary"; export const Route = createFileRoute("/dashboard/accounts")({ component: RouteComponent, @@ -92,7 +94,6 @@ function RouteComponent() { Add Account - )}
@@ -118,20 +119,26 @@ function RouteComponent() {
- + + +
- + + +
- + + +
diff --git a/client/src/routes/dashboard/home.tsx b/client/src/routes/dashboard/home.tsx index fd88df8f..8a023730 100644 --- a/client/src/routes/dashboard/home.tsx +++ b/client/src/routes/dashboard/home.tsx @@ -12,10 +12,7 @@ import { SidebarTrigger } from "@/core/components/ui/sidebar"; import { Button } from "@/core/components/ui/button"; import { LayoutDashboard, PlusCircle } from "lucide-react"; import { EmptyStateGuide } from "@/core/components/EmptyStateGuide"; - -// Import the loader and necessary types -// Optional: ErrorBoundary -// import { ErrorBoundary } from "react-error-boundary"; +import { ErrorBoundary } from "@/core/components/error-boundary"; export const Route = createFileRoute("/dashboard/home")({ component: RouteComponent, @@ -92,17 +89,18 @@ function RouteComponent() { if (!ChartToRender) return ; return ( - // Optional: ErrorBoundary - // }> - }> - - - // + } + > + }> + + + ); }))} diff --git a/client/src/routes/dashboard/records.tsx b/client/src/routes/dashboard/records.tsx index 31ef0b39..da40ca38 100644 --- a/client/src/routes/dashboard/records.tsx +++ b/client/src/routes/dashboard/records.tsx @@ -4,7 +4,7 @@ import { RecordsTable } from "@/features/transactions/components/records-table"; import { CalendarView } from "@/features/transactions/components/calendar-view"; import { Spinner } from "@/core/components/ui/spinner"; import { Button } from "@/core/components/ui/button"; -import { useState } from "react"; +import { useState, Suspense } from "react"; import { RecordsDialog } from "@/features/transactions/components/add-records-dialog"; import { NeuralRecordsDialog } from "@/features/transactions/components/neural-records-dialog"; @@ -16,6 +16,8 @@ import { LayoutDashboard, Plus, Sparkles, List, Calendar, BarChart3, ChevronDown import { SidebarTrigger } from "@/core/components/ui/sidebar"; import { EmptyStateGuide } from "@/core/components/EmptyStateGuide"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/core/components/ui/dropdown-menu"; +import { ErrorBoundary } from "@/core/components/error-boundary"; +import { TableLoader } from "@/core/components/loading"; const transactionFilterSchema = z.object({ page: z.number().catch(1), @@ -93,16 +95,22 @@ function RouteComponent() { switch (currentView) { case "list": return ( - + + }> + + + ); case "calendar": return ( - + + + ); case "analytics": return ( diff --git a/client/src/routes/dashboard/route.tsx b/client/src/routes/dashboard/route.tsx index 6e5bf626..d3906476 100644 --- a/client/src/routes/dashboard/route.tsx +++ b/client/src/routes/dashboard/route.tsx @@ -64,6 +64,7 @@ import { Theme } from "@/features/preferences/contexts/theme.context"; import { Spinner } from "@/core/components/ui/spinner"; import { useLogout } from "@/features/auth/services/auth.mutations"; import { getAllAccounts } from "@/features/accounts/services/account.queries"; +import { ErrorBoundary, ComponentErrorFallback } from "@/core/components/error-boundary"; export type ValidRoutes = keyof FileRoutesByTo; @@ -205,13 +206,17 @@ function DashboardWrapper() { - }> - - + + }> + + + - + + + ); diff --git a/client/tsconfig.tsbuildinfo b/client/tsconfig.tsbuildinfo index 007ef53c..10b13aa9 100644 --- a/client/tsconfig.tsbuildinfo +++ b/client/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./vite.env.d.ts","./vite.config.ts","./src/routeTree.gen.ts","./src/core/components/icon-picker/__tests__/index.helper.test.ts","./src/core/components/nested-select/utils.ts","./src/core/hooks/use-debounce.ts","./src/core/hooks/use-mobile.ts","./src/core/i18n/config.ts","./src/features/accounts/components/Account.type.ts","./src/features/accounts/components/account.utils.ts","./src/features/accounts/hooks/useBrand.ts","./src/features/accounts/hooks/useMono.ts","./src/features/accounts/services/account.queries.ts","./src/features/accounts/services/account.ts","./src/features/accounts/services/account.types.ts","./src/features/analytics/services/analytics.ts","./src/features/auth/services/auth.mutations.ts","./src/features/auth/services/auth.queries.ts","./src/features/auth/services/auth.ts","./src/features/auth/services/auth.types.ts","./src/features/auth/stores/auth.store.ts","./src/features/categories/services/category.ts","./src/features/categories/services/category.types.ts","./src/features/dashboard/charts/loader.ts","./src/features/dashboard/charts/store.ts","./src/features/dashboard/charts/types.ts","./src/features/dashboard/charts/account-balance-trends/index.ts","./src/features/dashboard/charts/budget-vs-actual/index.ts","./src/features/dashboard/charts/cash-flow-analysis/index.ts","./src/features/dashboard/charts/expense-income/index.ts","./src/features/dashboard/charts/investment-portfolio/index.ts","./src/features/dashboard/charts/monthly-spending-patterns/index.ts","./src/features/dashboard/services/chart.ts","./src/features/dashboard/stores/dashboard.store.ts","./src/features/onboarding/services/onboarding.ts","./src/features/onboarding/stores/onboarding.store.ts","./src/features/plugins/loader.ts","./src/features/plugins/store.ts","./src/features/plugins/types.ts","./src/features/plugins/real-estate/index.ts","./src/features/plugins/real-estate/store.ts","./src/features/plugins/real-estate/types.ts","./src/features/preferences/services/categories.service.ts","./src/features/preferences/services/feedback.queries.ts","./src/features/preferences/services/feedback.ts","./src/features/preferences/services/github-releases.queries.ts","./src/features/preferences/services/github-releases.service.ts","./src/features/preferences/services/merchants.service.ts","./src/features/preferences/services/merchants.ts","./src/features/preferences/services/meta.ts","./src/features/preferences/services/preferences.ts","./src/features/preferences/services/settings.queries.ts","./src/features/preferences/services/tags.service.ts","./src/features/preferences/services/tags.ts","./src/features/preferences/services/user.mutations.ts","./src/features/preferences/services/user.ts","./src/features/preferences/services/webhooks.service.ts","./src/features/preferences/services/webhooks.ts","./src/features/preferences/stores/preferences.store.ts","./src/features/preferences/stores/settings.store.ts","./src/features/preferences/stores/__tests__/settings.integration.test.ts","./src/features/preferences/stores/__tests__/settings.store.test.ts","./src/features/rules/services/rule.service.ts","./src/features/rules/services/rule.types.ts","./src/features/transactions/services/recurring-transaction.service.ts","./src/features/transactions/services/recurring-transaction.types.ts","./src/features/transactions/services/transaction.ts","./src/features/transactions/services/transaction.types.ts","./src/features/transactions/utils/transaction-status.ts","./src/lib/authed-query.ts","./src/lib/axios.ts","./src/lib/currency.ts","./src/lib/env.ts","./src/lib/error.ts","./src/lib/formatting.ts","./src/lib/logger.ts","./src/lib/trycatch.ts","./src/lib/utils.ts","./src/lib/__tests__/formatting.test.ts","./src/routes/dashboard_/settings/__tests__/settings-ui.test.ts","./src/types/mono-connect.d.ts","./src/app.tsx","./src/main.tsx","./src/router.tsx","./src/core/assets/icons/Burger.tsx","./src/core/assets/icons/ICWLG.tsx","./src/core/assets/icons/IconFull.tsx","./src/core/assets/icons/Logo.tsx","./src/core/assets/icons/apple.tsx","./src/core/assets/icons/github.tsx","./src/core/assets/icons/google.tsx","./src/core/components/EmptyStateGuide.tsx","./src/core/components/NotFound.tsx","./src/core/components/icon-picker/index.helper.tsx","./src/core/components/icon-picker/index.tsx","./src/core/components/layouts/mobile-burger.tsx","./src/core/components/nested-select/index.tsx","./src/core/components/ui/alert-dialog.tsx","./src/core/components/ui/alert.tsx","./src/core/components/ui/avatar.tsx","./src/core/components/ui/badge.tsx","./src/core/components/ui/breadcrumb.tsx","./src/core/components/ui/button.tsx","./src/core/components/ui/calendar.tsx","./src/core/components/ui/card.tsx","./src/core/components/ui/chart.tsx","./src/core/components/ui/checkbox.tsx","./src/core/components/ui/collapsible.tsx","./src/core/components/ui/color-picker.tsx","./src/core/components/ui/combobox.tsx","./src/core/components/ui/command.tsx","./src/core/components/ui/context-menu.tsx","./src/core/components/ui/date-picker.tsx","./src/core/components/ui/datetime.tsx","./src/core/components/ui/dialog-sheet.tsx","./src/core/components/ui/dialog.tsx","./src/core/components/ui/drawer.tsx","./src/core/components/ui/dropdown-menu.tsx","./src/core/components/ui/form.tsx","./src/core/components/ui/input-otp.tsx","./src/core/components/ui/input.tsx","./src/core/components/ui/inset-input.tsx","./src/core/components/ui/label.tsx","./src/core/components/ui/loading-spinner.tsx","./src/core/components/ui/overlap-input.tsx","./src/core/components/ui/popover.tsx","./src/core/components/ui/progress.tsx","./src/core/components/ui/radio-group.tsx","./src/core/components/ui/scroll-area.tsx","./src/core/components/ui/search-select.tsx","./src/core/components/ui/select.tsx","./src/core/components/ui/separator.tsx","./src/core/components/ui/sheet.tsx","./src/core/components/ui/sidebar.tsx","./src/core/components/ui/skeleton.tsx","./src/core/components/ui/sonner.tsx","./src/core/components/ui/spinner.tsx","./src/core/components/ui/switch.tsx","./src/core/components/ui/table.tsx","./src/core/components/ui/tabs.tsx","./src/core/components/ui/textarea.tsx","./src/core/components/ui/tooltip.tsx","./src/features/accounts/components/account.balance-chart.tsx","./src/features/accounts/components/account.constants.tsx","./src/features/accounts/components/account.create-modal.tsx","./src/features/accounts/components/account.delete-dialog.tsx","./src/features/accounts/components/account.edit-modal.tsx","./src/features/accounts/components/account.loading.tsx","./src/features/accounts/components/account.net-worth.tsx","./src/features/accounts/components/account.summary-card.tsx","./src/features/accounts/components/account.tsx","./src/features/accounts/components/csv-import-dialog.tsx","./src/features/analytics/components/budget-comparison-chart.tsx","./src/features/analytics/components/cashflow-forecast-chart.tsx","./src/features/analytics/components/category-breakdown-chart.tsx","./src/features/analytics/components/dashboard.loading.tsx","./src/features/analytics/components/dashboard.tsx","./src/features/analytics/components/expense-heatmap-chart.tsx","./src/features/analytics/components/financial-health-score.tsx","./src/features/analytics/components/income-expense-chart.tsx","./src/features/analytics/components/insight-card.tsx","./src/features/analytics/components/investment-performance-chart.tsx","./src/features/analytics/components/net-worth-chart.tsx","./src/features/analytics/components/savings-goal-chart.tsx","./src/features/analytics/components/spending-overview-chart.tsx","./src/features/auth/components/auth-interceptor.tsx","./src/features/dashboard/charts/account-balance-trends/component.tsx","./src/features/dashboard/charts/budget-vs-actual/component.tsx","./src/features/dashboard/charts/cash-flow-analysis/component.tsx","./src/features/dashboard/charts/expense-income/component.tsx","./src/features/dashboard/charts/investment-portfolio/component.tsx","./src/features/dashboard/charts/monthly-spending-patterns/component.tsx","./src/features/dashboard/components/add-chart.tsx","./src/features/dashboard/components/dashboard-grid.tsx","./src/features/dashboard/components/chart-card/chart-card.loading.tsx","./src/features/dashboard/components/chart-card/chart-renderer.tsx","./src/features/dashboard/components/chart-card/index.tsx","./src/features/dashboard/hooks/useLazyChart.tsx","./src/features/plugins/real-estate/components/add-property-dialog.tsx","./src/features/plugins/real-estate/components/morgage-payment-chart.tsx","./src/features/plugins/real-estate/components/property-card.tsx","./src/features/plugins/real-estate/components/property-value-chart.tsx","./src/features/plugins/real-estate/components/rental-income-chart.tsx","./src/features/plugins/real-estate/pages/analytics.tsx","./src/features/plugins/real-estate/pages/map.tsx","./src/features/plugins/real-estate/pages/overview.tsx","./src/features/plugins/real-estate/pages/properties.tsx","./src/features/plugins/real-estate/pages/settings.tsx","./src/features/preferences/components/preferences-provider.tsx","./src/features/preferences/contexts/theme.context.tsx","./src/features/preferences/contexts/theme.provider.tsx","./src/features/preferences/hooks/use-theme.tsx","./src/features/rules/components/create-rule-dialog.tsx","./src/features/rules/components/edit-rule-dialog.tsx","./src/features/rules/components/rule-action-badge.tsx","./src/features/rules/components/rule-condition-badge.tsx","./src/features/rules/components/rules-management.tsx","./src/features/transactions/components/add-records-dialog.tsx","./src/features/transactions/components/bulk-approval-dialog.tsx","./src/features/transactions/components/bulk-edit-dialog.tsx","./src/features/transactions/components/calendar-view.tsx","./src/features/transactions/components/create-edit-rule-dialog.tsx","./src/features/transactions/components/custom-recurring-modal.tsx","./src/features/transactions/components/del-records-dialog.tsx","./src/features/transactions/components/edt-records-sheet.tsx","./src/features/transactions/components/filter-demo.tsx","./src/features/transactions/components/floating-records-bar.tsx","./src/features/transactions/components/import-transactions-dialog.tsx","./src/features/transactions/components/neural-records-dialog.tsx","./src/features/transactions/components/pending-transactions-dashboard.tsx","./src/features/transactions/components/records-table.column.tsx","./src/features/transactions/components/records-table.loading.tsx","./src/features/transactions/components/records-table.tsx","./src/features/transactions/components/recurring-select.tsx","./src/features/transactions/components/recurring-transaction-form.tsx","./src/features/transactions/components/rules-dialog.tsx","./src/features/transactions/components/transaction-filter-dropdown.tsx","./src/features/transactions/components/transaction-filters.tsx","./src/routes/__root.tsx","./src/routes/forgot-password.tsx","./src/routes/import-demo.tsx","./src/routes/index.tsx","./src/routes/login.tsx","./src/routes/signup.tsx","./src/routes/dashboard/$.tsx","./src/routes/dashboard/accounts.$id.tsx","./src/routes/dashboard/accounts.tsx","./src/routes/dashboard/analytics.tsx","./src/routes/dashboard/home.tsx","./src/routes/dashboard/index.tsx","./src/routes/dashboard/records.tsx","./src/routes/dashboard/route.tsx","./src/routes/dashboard_/settings/appearance.tsx","./src/routes/dashboard_/settings/categories.tsx","./src/routes/dashboard_/settings/currencies.tsx","./src/routes/dashboard_/settings/features.tsx","./src/routes/dashboard_/settings/feedback.tsx","./src/routes/dashboard_/settings/index.tsx","./src/routes/dashboard_/settings/localization.tsx","./src/routes/dashboard_/settings/merchants.tsx","./src/routes/dashboard_/settings/news.tsx","./src/routes/dashboard_/settings/profile.tsx","./src/routes/dashboard_/settings/route.tsx","./src/routes/dashboard_/settings/rules.tsx","./src/routes/dashboard_/settings/security.tsx","./src/routes/dashboard_/settings/tags.tsx","./src/routes/dashboard_/settings/webhooks.tsx","./src/routes/dashboard_/settings/-components/tag-list.tsx","./src/routes/onboarding/complexity.tsx","./src/routes/onboarding/features.tsx","./src/routes/onboarding/finance-interest.tsx","./src/routes/onboarding/goals.tsx","./src/routes/onboarding/index.tsx","./src/routes/onboarding/name.tsx","./src/routes/onboarding/route.tsx","./src/routes/onboarding/social-proof.tsx"],"errors":true,"version":"5.8.3"} \ No newline at end of file +{"root":["./vite.env.d.ts","./vite.config.ts","./src/routeTree.gen.ts","./src/core/components/icon-picker/__tests__/index.helper.test.ts","./src/core/components/nested-select/utils.ts","./src/core/hooks/use-debounce.ts","./src/core/hooks/use-mobile.ts","./src/core/i18n/config.ts","./src/features/accounts/components/Account.type.ts","./src/features/accounts/components/account.utils.ts","./src/features/accounts/hooks/useBrand.ts","./src/features/accounts/hooks/useMono.ts","./src/features/accounts/services/account.queries.ts","./src/features/accounts/services/account.ts","./src/features/accounts/services/account.types.ts","./src/features/analytics/services/analytics.ts","./src/features/auth/services/auth.mutations.ts","./src/features/auth/services/auth.queries.ts","./src/features/auth/services/auth.ts","./src/features/auth/services/auth.types.ts","./src/features/auth/stores/auth.store.ts","./src/features/categories/services/category.ts","./src/features/categories/services/category.types.ts","./src/features/dashboard/charts/loader.ts","./src/features/dashboard/charts/store.ts","./src/features/dashboard/charts/types.ts","./src/features/dashboard/charts/expense-income/index.ts","./src/features/dashboard/services/chart.ts","./src/features/dashboard/stores/dashboard.store.ts","./src/features/onboarding/services/onboarding.ts","./src/features/onboarding/stores/onboarding.store.ts","./src/features/plugins/loader.ts","./src/features/plugins/store.ts","./src/features/plugins/types.ts","./src/features/plugins/real-estate/index.ts","./src/features/plugins/real-estate/store.ts","./src/features/plugins/real-estate/types.ts","./src/features/preferences/services/categories.service.ts","./src/features/preferences/services/feedback.queries.ts","./src/features/preferences/services/feedback.ts","./src/features/preferences/services/github-releases.queries.ts","./src/features/preferences/services/github-releases.service.ts","./src/features/preferences/services/merchants.service.ts","./src/features/preferences/services/merchants.ts","./src/features/preferences/services/meta.ts","./src/features/preferences/services/preferences.ts","./src/features/preferences/services/settings.queries.ts","./src/features/preferences/services/tags.service.ts","./src/features/preferences/services/tags.ts","./src/features/preferences/services/user.mutations.ts","./src/features/preferences/services/user.ts","./src/features/preferences/services/webhooks.service.ts","./src/features/preferences/services/webhooks.ts","./src/features/preferences/stores/preferences.store.ts","./src/features/preferences/stores/settings.store.ts","./src/features/preferences/stores/__tests__/settings.integration.test.ts","./src/features/preferences/stores/__tests__/settings.store.test.ts","./src/features/rules/services/rule.service.ts","./src/features/rules/services/rule.types.ts","./src/features/transactions/services/recurring-transaction.service.ts","./src/features/transactions/services/recurring-transaction.types.ts","./src/features/transactions/services/transaction.ts","./src/features/transactions/services/transaction.types.ts","./src/features/transactions/utils/transaction-status.ts","./src/lib/authed-query.ts","./src/lib/axios.ts","./src/lib/currency.ts","./src/lib/env.ts","./src/lib/error.ts","./src/lib/formatting.ts","./src/lib/logger.ts","./src/lib/trycatch.ts","./src/lib/utils.ts","./src/lib/__tests__/formatting.test.ts","./src/routes/dashboard_/settings/__tests__/settings-ui.test.ts","./src/types/mono-connect.d.ts","./src/app.tsx","./src/main.tsx","./src/router.tsx","./src/core/assets/icons/Burger.tsx","./src/core/assets/icons/ICWLG.tsx","./src/core/assets/icons/IconFull.tsx","./src/core/assets/icons/Logo.tsx","./src/core/assets/icons/apple.tsx","./src/core/assets/icons/github.tsx","./src/core/assets/icons/google.tsx","./src/core/components/EmptyStateGuide.tsx","./src/core/components/NotFound.tsx","./src/core/components/error-boundary/component-error-fallback.tsx","./src/core/components/error-boundary/error-fallback.tsx","./src/core/components/error-boundary/index.tsx","./src/core/components/error-boundary/route-error-fallback.tsx","./src/core/components/icon-picker/index.helper.tsx","./src/core/components/icon-picker/index.tsx","./src/core/components/layouts/mobile-burger.tsx","./src/core/components/loading/index.tsx","./src/core/components/nested-select/index.tsx","./src/core/components/ui/alert-dialog.tsx","./src/core/components/ui/alert.tsx","./src/core/components/ui/avatar.tsx","./src/core/components/ui/badge.tsx","./src/core/components/ui/breadcrumb.tsx","./src/core/components/ui/button.tsx","./src/core/components/ui/calendar.tsx","./src/core/components/ui/card.tsx","./src/core/components/ui/chart.tsx","./src/core/components/ui/checkbox.tsx","./src/core/components/ui/collapsible.tsx","./src/core/components/ui/color-picker.tsx","./src/core/components/ui/combobox.tsx","./src/core/components/ui/command.tsx","./src/core/components/ui/context-menu.tsx","./src/core/components/ui/date-picker.tsx","./src/core/components/ui/datetime.tsx","./src/core/components/ui/dialog-sheet.tsx","./src/core/components/ui/dialog.tsx","./src/core/components/ui/drawer.tsx","./src/core/components/ui/dropdown-menu.tsx","./src/core/components/ui/form.tsx","./src/core/components/ui/input-otp.tsx","./src/core/components/ui/input.tsx","./src/core/components/ui/inset-input.tsx","./src/core/components/ui/label.tsx","./src/core/components/ui/loading-spinner.tsx","./src/core/components/ui/overlap-input.tsx","./src/core/components/ui/popover.tsx","./src/core/components/ui/progress.tsx","./src/core/components/ui/radio-group.tsx","./src/core/components/ui/scroll-area.tsx","./src/core/components/ui/search-select.tsx","./src/core/components/ui/select.tsx","./src/core/components/ui/separator.tsx","./src/core/components/ui/sheet.tsx","./src/core/components/ui/sidebar.tsx","./src/core/components/ui/skeleton.tsx","./src/core/components/ui/sonner.tsx","./src/core/components/ui/spinner.tsx","./src/core/components/ui/switch.tsx","./src/core/components/ui/table.tsx","./src/core/components/ui/tabs.tsx","./src/core/components/ui/textarea.tsx","./src/core/components/ui/tooltip.tsx","./src/features/accounts/components/account.balance-chart.tsx","./src/features/accounts/components/account.constants.tsx","./src/features/accounts/components/account.create-modal.tsx","./src/features/accounts/components/account.delete-dialog.tsx","./src/features/accounts/components/account.edit-modal.tsx","./src/features/accounts/components/account.loading.tsx","./src/features/accounts/components/account.net-worth.tsx","./src/features/accounts/components/account.summary-card.tsx","./src/features/accounts/components/account.tsx","./src/features/accounts/components/csv-import-dialog.tsx","./src/features/analytics/components/budget-comparison-chart.tsx","./src/features/analytics/components/cashflow-forecast-chart.tsx","./src/features/analytics/components/category-breakdown-chart.tsx","./src/features/analytics/components/dashboard.loading.tsx","./src/features/analytics/components/dashboard.tsx","./src/features/analytics/components/expense-heatmap-chart.tsx","./src/features/analytics/components/financial-health-score.tsx","./src/features/analytics/components/income-expense-chart.tsx","./src/features/analytics/components/insight-card.tsx","./src/features/analytics/components/investment-performance-chart.tsx","./src/features/analytics/components/net-worth-chart.tsx","./src/features/analytics/components/savings-goal-chart.tsx","./src/features/analytics/components/spending-overview-chart.tsx","./src/features/auth/components/auth-interceptor.tsx","./src/features/dashboard/charts/expense-income/component.tsx","./src/features/dashboard/components/add-chart.tsx","./src/features/dashboard/components/dashboard-grid.tsx","./src/features/dashboard/components/chart-card/chart-card.loading.tsx","./src/features/dashboard/components/chart-card/chart-renderer.tsx","./src/features/dashboard/components/chart-card/index.tsx","./src/features/dashboard/hooks/useLazyChart.tsx","./src/features/plugins/real-estate/components/add-property-dialog.tsx","./src/features/plugins/real-estate/components/morgage-payment-chart.tsx","./src/features/plugins/real-estate/components/property-card.tsx","./src/features/plugins/real-estate/components/property-value-chart.tsx","./src/features/plugins/real-estate/components/rental-income-chart.tsx","./src/features/plugins/real-estate/pages/analytics.tsx","./src/features/plugins/real-estate/pages/map.tsx","./src/features/plugins/real-estate/pages/overview.tsx","./src/features/plugins/real-estate/pages/properties.tsx","./src/features/plugins/real-estate/pages/settings.tsx","./src/features/preferences/components/preferences-provider.tsx","./src/features/preferences/contexts/theme.context.tsx","./src/features/preferences/contexts/theme.provider.tsx","./src/features/preferences/hooks/use-theme.tsx","./src/features/rules/components/create-rule-dialog.tsx","./src/features/rules/components/edit-rule-dialog.tsx","./src/features/rules/components/rule-action-badge.tsx","./src/features/rules/components/rule-condition-badge.tsx","./src/features/rules/components/rules-management.tsx","./src/features/transactions/components/add-records-dialog.tsx","./src/features/transactions/components/bulk-approval-dialog.tsx","./src/features/transactions/components/bulk-edit-dialog.tsx","./src/features/transactions/components/calendar-view.tsx","./src/features/transactions/components/create-edit-rule-dialog.tsx","./src/features/transactions/components/custom-recurring-modal.tsx","./src/features/transactions/components/del-records-dialog.tsx","./src/features/transactions/components/edt-records-sheet.tsx","./src/features/transactions/components/filter-demo.tsx","./src/features/transactions/components/floating-records-bar.tsx","./src/features/transactions/components/import-transactions-dialog.tsx","./src/features/transactions/components/neural-records-dialog.tsx","./src/features/transactions/components/pending-transactions-dashboard.tsx","./src/features/transactions/components/records-table.column.tsx","./src/features/transactions/components/records-table.loading.tsx","./src/features/transactions/components/records-table.tsx","./src/features/transactions/components/recurring-select.tsx","./src/features/transactions/components/recurring-transaction-form.tsx","./src/features/transactions/components/rules-dialog.tsx","./src/features/transactions/components/transaction-filter-dropdown.tsx","./src/features/transactions/components/transaction-filters.tsx","./src/routes/__root.tsx","./src/routes/forgot-password.tsx","./src/routes/import-demo.tsx","./src/routes/index.tsx","./src/routes/login.tsx","./src/routes/signup.tsx","./src/routes/dashboard/$.tsx","./src/routes/dashboard/accounts.$id.tsx","./src/routes/dashboard/accounts.tsx","./src/routes/dashboard/analytics.tsx","./src/routes/dashboard/home.tsx","./src/routes/dashboard/index.tsx","./src/routes/dashboard/records.tsx","./src/routes/dashboard/route.tsx","./src/routes/dashboard_/settings/appearance.tsx","./src/routes/dashboard_/settings/categories.tsx","./src/routes/dashboard_/settings/currencies.tsx","./src/routes/dashboard_/settings/features.tsx","./src/routes/dashboard_/settings/feedback.tsx","./src/routes/dashboard_/settings/index.tsx","./src/routes/dashboard_/settings/localization.tsx","./src/routes/dashboard_/settings/merchants.tsx","./src/routes/dashboard_/settings/news.tsx","./src/routes/dashboard_/settings/profile.tsx","./src/routes/dashboard_/settings/route.tsx","./src/routes/dashboard_/settings/rules.tsx","./src/routes/dashboard_/settings/security.tsx","./src/routes/dashboard_/settings/tags.tsx","./src/routes/dashboard_/settings/webhooks.tsx","./src/routes/dashboard_/settings/-components/tag-list.tsx","./src/routes/onboarding/complexity.tsx","./src/routes/onboarding/features.tsx","./src/routes/onboarding/finance-interest.tsx","./src/routes/onboarding/goals.tsx","./src/routes/onboarding/index.tsx","./src/routes/onboarding/name.tsx","./src/routes/onboarding/route.tsx","./src/routes/onboarding/social-proof.tsx"],"errors":true,"version":"5.7.3"} diff --git a/client/vite.config.ts b/client/vite.config.ts index af87a8c1..4bdbe824 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -20,4 +20,21 @@ export default defineConfig({ tailwindcss(), tsConfigPaths(), ], + build: { + rollupOptions: { + output: { + manualChunks: { + // Separate vendor chunks for better caching + 'react-vendor': ['react', 'react-dom'], + 'query-vendor': ['@tanstack/react-query', '@tanstack/react-router'], + 'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu', '@radix-ui/react-select', '@radix-ui/react-tabs'], + 'chart-vendor': ['recharts'], + 'form-vendor': ['react-hook-form', '@hookform/resolvers', 'zod'], + 'utils-vendor': ['date-fns', 'clsx', 'tailwind-merge'], + }, + }, + }, + // Increase chunk size warning limit since we're optimizing + chunkSizeWarningLimit: 1000, + }, });