diff --git a/main.go b/main.go
index 03297c98..eddb7419 100644
--- a/main.go
+++ b/main.go
@@ -181,6 +181,12 @@ func main() {
<-quit
logger.Info("📴 Shutdown signal received, closing system...")
+ // Gracefully shutdown HTTP server (drain in-flight requests)
+ if err := server.Shutdown(); err != nil {
+ logger.Warnf("⚠️ HTTP server shutdown error: %v", err)
+ }
+ logger.Info("✅ HTTP server stopped")
+
// Stop all traders
traderManager.StopAll()
logger.Info("✅ System shut down safely")
diff --git a/web/src/App.tsx b/web/src/App.tsx
index 211be224..e5237b51 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -18,6 +18,7 @@ import { StrategyMarketPage } from './pages/StrategyMarketPage'
import { DataPage } from './pages/DataPage'
import { LoginRequiredOverlay } from './components/auth/LoginRequiredOverlay'
import HeaderBar from './components/common/HeaderBar'
+import { ErrorBoundary } from './components/common/ErrorBoundary'
import { LanguageProvider, useLanguage } from './contexts/LanguageContext'
import { AuthProvider, useAuth } from './contexts/AuthContext'
import { ConfirmDialogProvider } from './components/common/ConfirmDialog'
@@ -396,7 +397,9 @@ function App() {
onLoginRequired={handleLoginRequired}
onPageChange={navigateToPage}
/>
-
+
+
+
)
}
@@ -474,6 +477,7 @@ function App() {
{/* Main Content with Page Transitions */}
+
+
{/* Footer */}
diff --git a/web/src/components/charts/ChartTabs.tsx b/web/src/components/charts/ChartTabs.tsx
index 8c9fde0e..4e237c0e 100644
--- a/web/src/components/charts/ChartTabs.tsx
+++ b/web/src/components/charts/ChartTabs.tsx
@@ -144,8 +144,7 @@ export function ChartTabs({ traderId, selectedSymbol, updateKey, exchangeId }: C
return (
-
+
{/*
Premium Professional Toolbar
Mobile: Single row, horizontal scroll with gradient mask
diff --git a/web/src/components/common/ErrorBoundary.tsx b/web/src/components/common/ErrorBoundary.tsx
new file mode 100644
index 00000000..22540684
--- /dev/null
+++ b/web/src/components/common/ErrorBoundary.tsx
@@ -0,0 +1,61 @@
+import { Component, type ReactNode } from 'react'
+import { AlertTriangle, RefreshCw } from 'lucide-react'
+
+interface Props {
+ children: ReactNode
+ fallback?: ReactNode
+}
+
+interface State {
+ hasError: boolean
+ error: Error | null
+}
+
+export class ErrorBoundary extends Component
{
+ constructor(props: Props) {
+ super(props)
+ this.state = { hasError: false, error: null }
+ }
+
+ static getDerivedStateFromError(error: Error): State {
+ return { hasError: true, error }
+ }
+
+ componentDidCatch(error: Error, info: React.ErrorInfo) {
+ console.error('[ErrorBoundary] Uncaught error:', error, info.componentStack)
+ }
+
+ handleReset = () => {
+ this.setState({ hasError: false, error: null })
+ }
+
+ render() {
+ if (this.state.hasError) {
+ if (this.props.fallback) return this.props.fallback
+
+ return (
+
+
+
Something went wrong
+
+ An unexpected error occurred. You can try refreshing this section.
+
+ {this.state.error && (
+
+ {this.state.error.message}
+
+ )}
+
+
+ )
+ }
+
+ return this.props.children
+ }
+}