refactor: split AppShell, match-detail panels, extract useCompareData
AppShell.tsx: 627→116 lines - appShellConfig.ts: NavItem/WorkspaceConfig types, WORKSPACE_CONFIG, nav helpers - AppShellSidebar.tsx: Sidebar component with visual constants - AppShellTopBar.tsx: TopBar component Match-detail panels: - ScoreBreakdownPanel: 377→303 lines (scoreBreakdownConstants.ts + CriterionRow.tsx extracted) - LocationIntelligencePanel: 383→333 lines (SoftFactorBar.tsx extracted) - FutureAvailabilityContextPanel: 386→351 lines (futureAvailabilityConstants.tsx extracted) Compare.tsx: 485→441 lines - useCompareData hook: all queries and derived state extracted to hooks/useCompareData.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Box, Chip, Divider, LinearProgress, Paper, Tooltip, Typography } from '@mui/material'
|
||||
import { Box, Chip, Divider, Paper, Typography } from '@mui/material'
|
||||
import {
|
||||
Activity, Building2, HardHat, MapPin, Percent,
|
||||
TrendingDown, TrendingUp, Train, Users, Zap,
|
||||
@@ -7,60 +7,10 @@ import { useNavigate } from 'react-router'
|
||||
import { useProperties } from '../../hooks/useProperties'
|
||||
import { getCityIntelligence } from '../../lib/locationIntelligence'
|
||||
import type { Property } from '../../domain/property'
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
function scoreColor(v: number) {
|
||||
if (v >= 0.72) return '#1a7a4a'
|
||||
if (v >= 0.48) return '#d97706'
|
||||
return '#c0392b'
|
||||
}
|
||||
|
||||
function scoreLabel(v: number) {
|
||||
if (v >= 0.82) return 'Sehr gut'
|
||||
if (v >= 0.65) return 'Gut'
|
||||
if (v >= 0.45) return 'Mittel'
|
||||
return 'Schwach'
|
||||
}
|
||||
import { SoftFactorBar } from './SoftFactorBar'
|
||||
|
||||
// ── Sub-components ────────────────────────────────────────────────────────────
|
||||
|
||||
function SoftFactorBar({
|
||||
label,
|
||||
value,
|
||||
icon,
|
||||
tooltip,
|
||||
}: {
|
||||
label: string
|
||||
value: number | undefined | null
|
||||
icon: React.ReactNode
|
||||
tooltip?: string
|
||||
}) {
|
||||
if (value === undefined || value === null) return null
|
||||
const color = scoreColor(value)
|
||||
const row = (
|
||||
<Box sx={{ mb: 1.5 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 0.4 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75 }}>
|
||||
<Box sx={{ color: '#64748b', display: 'flex' }}>{icon}</Box>
|
||||
<Typography variant="body2">{label}</Typography>
|
||||
</Box>
|
||||
<Chip
|
||||
label={scoreLabel(value)}
|
||||
size="small"
|
||||
sx={{ bgcolor: color, color: 'white', fontSize: 10, height: 18, fontWeight: 600 }}
|
||||
/>
|
||||
</Box>
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={value * 100}
|
||||
sx={{ height: 5, borderRadius: 3, bgcolor: '#f1f5f9', '& .MuiLinearProgress-bar': { bgcolor: color } }}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
return tooltip ? <Tooltip title={tooltip} placement="left">{row}</Tooltip> : row
|
||||
}
|
||||
|
||||
function KpiTile({
|
||||
label,
|
||||
value,
|
||||
|
||||
Reference in New Issue
Block a user