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:
Benjamin Sutter
2026-05-24 01:00:38 +02:00
parent ae82d0e6a0
commit 0bacd188d6
13 changed files with 792 additions and 741 deletions
@@ -1,54 +1,19 @@
import { Box, Button, Chip, Divider, LinearProgress, Paper, Typography } from '@mui/material'
import {
AlertTriangle,
BarChart2,
Briefcase,
Calendar,
CheckCircle2,
Clock,
ExternalLink,
FileCheck,
FileText,
Globe,
Newspaper,
ShieldCheck,
Sparkles,
TrendingUp,
User,
Zap,
} from 'lucide-react'
import type { Match } from '../../domain/match'
import type { FutureSignal } from '../../domain/futureSignal'
const SIGNAL_TYPE_LABELS: Record<string, string> = {
EXPANSION: 'Expansion',
POSSIBLE_MOVE_OUT: 'Möglicher Auszug',
CONSTRUCTION_PROJECT: 'Bauvorhaben',
RESTRUCTURING: 'Restrukturierung',
PROJECT_DEVELOPMENT: 'Projektentwicklung',
SPACE_CONSOLIDATION: 'Flächenkonsolidierung',
LEASE_EXPIRY: 'Vertragsende (Pre-Market)',
}
const SIGNAL_ACTION: Record<string, { label: string; urgency: 'high' | 'medium' | 'low' }> = {
EXPANSION: { label: 'Unternehmen proaktiv kontaktieren — aktive Flächensuche wahrscheinlich', urgency: 'high' },
POSSIBLE_MOVE_OUT: { label: 'Mieter ansprechen und Verlängerungsgespräch initiieren', urgency: 'high' },
CONSTRUCTION_PROJECT: { label: 'Frühzeitiges Interesse beim Bauherrn anmelden, bevor Vermietungsmandat vergeben', urgency: 'medium' },
RESTRUCTURING: { label: 'Situation beobachten, bei Bestätigung sofort handeln', urgency: 'medium' },
PROJECT_DEVELOPMENT: { label: 'Entwicklungsfortschritt monitoren und Kontakt zum Projektentwickler suchen', urgency: 'medium' },
SPACE_CONSOLIDATION: { label: 'Teilflächen-Anforderungen klären, Gespräch mit Verwaltung suchen', urgency: 'medium' },
LEASE_EXPIRY: { label: 'Anfrage direkt über die Verwaltung stellen — Fläche ist für Matching freigegeben', urgency: 'high' },
}
const SOURCE_META: Record<string, { label: string; icon: React.ReactNode }> = {
JOB_POSTING: { label: 'Stelleninserate', icon: <Briefcase size={13} /> },
PRESS: { label: 'Pressebericht', icon: <Newspaper size={13} /> },
CONSTRUCTION_PERMIT: { label: 'Baubewilligung', icon: <FileCheck size={13} /> },
COMPANY_REPORT: { label: 'Geschäftsbericht', icon: <FileText size={13} /> },
MARKET_DATA: { label: 'Marktdaten', icon: <BarChart2 size={13} /> },
MANUAL: { label: 'Analyst', icon: <User size={13} /> },
LEASE_CONTRACT: { label: 'Vertrag verifiziert (ERP)', icon: <ShieldCheck size={13} /> },
}
import { SIGNAL_TYPE_LABELS, SIGNAL_ACTION, SOURCE_META } from './futureAvailabilityConstants'
const CREDIBILITY_META: Record<string, { label: string; color: string }> = {
HIGH: { label: 'Hohe Quellenqualität', color: '#1a7a4a' },