fase(25): polish and quality improvements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ import { LicenseSection } from '@/pages/settings/LicenseSection'
|
||||
import { SchedulesSection } from '@/pages/settings/SchedulesSection'
|
||||
import { Reports } from '@/pages/Reports'
|
||||
import { VisualReview } from '@/pages/VisualReview'
|
||||
import { ErrorBoundary } from '@/components/layout/ErrorBoundary'
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -42,13 +43,13 @@ export default function App() {
|
||||
</ProtectedRoute>
|
||||
}
|
||||
>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route path="/sessions" element={<SessionList />} />
|
||||
<Route path="/sessions/:id" element={<SessionDetail />} />
|
||||
<Route path="/findings" element={<FindingsList />} />
|
||||
<Route path="/findings/:id" element={<FindingDetail />} />
|
||||
<Route path="/reports" element={<Reports />} />
|
||||
<Route path="/visual-review" element={<VisualReview />} />
|
||||
<Route path="/" element={<ErrorBoundary><Dashboard /></ErrorBoundary>} />
|
||||
<Route path="/sessions" element={<ErrorBoundary><SessionList /></ErrorBoundary>} />
|
||||
<Route path="/sessions/:id" element={<ErrorBoundary><SessionDetail /></ErrorBoundary>} />
|
||||
<Route path="/findings" element={<ErrorBoundary><FindingsList /></ErrorBoundary>} />
|
||||
<Route path="/findings/:id" element={<ErrorBoundary><FindingDetail /></ErrorBoundary>} />
|
||||
<Route path="/reports" element={<ErrorBoundary><Reports /></ErrorBoundary>} />
|
||||
<Route path="/visual-review" element={<ErrorBoundary><VisualReview /></ErrorBoundary>} />
|
||||
<Route path="/settings" element={<SettingsLayout />}>
|
||||
<Route index element={<Navigate to="profile" replace />} />
|
||||
<Route path="profile" element={<ProfileSection />} />
|
||||
|
||||
54
frontend/src/components/layout/ErrorBoundary.tsx
Normal file
54
frontend/src/components/layout/ErrorBoundary.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Component, type ReactNode } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
|
||||
interface Props {
|
||||
children: ReactNode
|
||||
fallback?: ReactNode
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean
|
||||
error: Error | null
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { hasError: false, error: null }
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): State {
|
||||
return { hasError: true, error }
|
||||
}
|
||||
|
||||
handleReset = () => {
|
||||
this.setState({ hasError: false, error: null })
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
if (this.props.fallback) return this.props.fallback
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[400px] p-6">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-destructive">Something went wrong</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{this.state.error?.message ?? 'An unexpected error occurred.'}
|
||||
</p>
|
||||
<Button onClick={this.handleReset} variant="outline">
|
||||
Try again
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return this.props.children
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user