fix: resolve all TypeScript errors and refactor oversized components
- Fix MUI v9 API: PaperProps/InputLabelProps/inputProps → slotProps in 6 components - Add ExternalMarketResult alias, PropertyUnit import, OPERATIONS workspace config - Fix TradeOff.description → .concern, ScoreFactor.label → .criterion - Make schattenmarktRelease.leadTimeMonths optional, fix mock-data enum values - Fix useMatchDetailData query typing, weightingService missing WeightProfile keys - Split Pipeline/Compare/MatchDetail/IntelligenceMatchCard into sub-components - Fix all test fixtures (CreateNeedInput, CreatePropertyInput, TradeOffInput, etc.) - Add vercel.json for deployment, zero tsc errors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,6 @@ import { Search, Send, Paperclip, ArrowLeft, Bot, Building2, Kanban } from 'luci
|
||||
import { mockDemandInquiries } from '../../mock-data/demandInquiries'
|
||||
import { useInquiryStore } from '../../stores/inquiryStore'
|
||||
import { usePipelineItems, useMoveStage } from '../../hooks/usePipeline'
|
||||
import { useToastStore } from '../../stores/toastStore'
|
||||
import type { InquiryMessage } from '../../domain/inquiry'
|
||||
import { STAGE_ORDER, STAGE_LABELS, detectKiStage } from './anfragenKiDetection'
|
||||
import { AnfragenMessageBubble } from '../../components/demand/AnfragenMessageBubble'
|
||||
@@ -32,7 +31,7 @@ export default function Anfragen() {
|
||||
const [searchParams] = useSearchParams()
|
||||
const { data: pipelineItems = [] } = usePipelineItems()
|
||||
const { mutate: moveStage } = useMoveStage()
|
||||
const showToast = useToastStore(s => s.showToast)
|
||||
|
||||
|
||||
const preselectedId = searchParams.get('inquiry')
|
||||
|
||||
@@ -156,7 +155,7 @@ export default function Anfragen() {
|
||||
<TextField
|
||||
size="small" placeholder="Suchen..." fullWidth
|
||||
value={search} onChange={e => setSearch(e.target.value)}
|
||||
InputProps={{ startAdornment: <InputAdornment position="start"><Search size={14} color={DS_TEXT.disabled} /></InputAdornment> }}
|
||||
slotProps={{ input: { startAdornment: <InputAdornment position="start"><Search size={14} color={DS_TEXT.disabled} /></InputAdornment> } }}
|
||||
sx={{ mb: 1.25 }}
|
||||
/>
|
||||
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>
|
||||
|
||||
@@ -41,7 +41,6 @@ export default function Compare() {
|
||||
overallWinnerIdx,
|
||||
bestScoreIdx,
|
||||
worstConfIdx,
|
||||
dqScores,
|
||||
worstDQIdx,
|
||||
missingCriticalCounts,
|
||||
maxMissingCritical,
|
||||
|
||||
@@ -1,31 +1,19 @@
|
||||
import { useState } from 'react'
|
||||
import { InquiryQuickDialog } from '../../components/match-detail/InquiryQuickDialog'
|
||||
import { Box, Button, Chip, CircularProgress, Paper, Typography } from '@mui/material'
|
||||
import { AlertTriangle, ArrowLeft, ChevronDown, ChevronUp } from 'lucide-react'
|
||||
import { AlertTriangle, ArrowLeft } from 'lucide-react'
|
||||
import { useNavigate, useParams } from 'react-router'
|
||||
import { useCompareStore } from '../../stores/compareStore'
|
||||
import { usePipelineStore } from '../../stores/pipelineStore'
|
||||
import { useInquiryStore } from '../../stores/inquiryStore'
|
||||
import { AddToPipelineDialog } from '../../components/shortlist'
|
||||
import { MatchReasonList } from '../../components/match-card/MatchReasonList'
|
||||
import { PropertyMap } from '../../components/shared'
|
||||
import { getCityIntelligence } from '../../lib/locationIntelligence'
|
||||
import {
|
||||
LocationIntelligencePanel,
|
||||
ExecutiveSummaryPanel,
|
||||
NeedAlignmentPanel,
|
||||
ScoreBreakdownPanel,
|
||||
TradeoffPanel,
|
||||
RiskPanel,
|
||||
MissingInformationPanel,
|
||||
FutureAvailabilityContextPanel,
|
||||
NextActionsPanel,
|
||||
} from '../../components/match-detail'
|
||||
import { NextActionsPanel } from '../../components/match-detail'
|
||||
import type { MatchCardReason } from '../../components/match-card/MatchCardViewModel'
|
||||
import { useMatchDetailData } from '../../hooks/useMatchDetailData'
|
||||
import { useMatchDetail } from '../../hooks/useMatches'
|
||||
import { MatchDetailHero } from '../../components/match-detail/MatchDetailHero'
|
||||
import { MatchDetailPropertySections } from '../../components/match-detail/MatchDetailPropertySections'
|
||||
import { MatchDetailScoreBreakdown } from '../../components/match-detail/MatchDetailScoreBreakdown'
|
||||
import { RESULT_TYPE_META, DS_TEXT, DS_SURFACE, DS_BORDER, DS_BG } from '../../lib/ds'
|
||||
|
||||
// ── helpers ───────────────────────────────────────────────────────────────────
|
||||
@@ -49,7 +37,6 @@ export default function MatchDetail() {
|
||||
const { addToCompare } = useCompareStore()
|
||||
const { openSavedDialog } = usePipelineStore()
|
||||
const { openInquiryDialog } = useInquiryStore()
|
||||
const [showFullAnalysis, setShowFullAnalysis] = useState(false)
|
||||
|
||||
const { match, property, need, signal, isLoading, isFuture } = useMatchDetailData(matchId ?? '')
|
||||
|
||||
@@ -91,7 +78,7 @@ export default function MatchDetail() {
|
||||
const handleCompare = () => {
|
||||
if (match && !isFuture && property) {
|
||||
addToCompare({
|
||||
resultType: property.resultType ?? 'VERIFIED_PORTFOLIO',
|
||||
resultType: (property.resultType ?? 'VERIFIED_PORTFOLIO') as 'VERIFIED_PORTFOLIO' | 'MAISON_WORK',
|
||||
matchId: match.id, needId: match.needId, matchScore: match.matchScore, match, property,
|
||||
})
|
||||
} else if (match && isFuture && signal) {
|
||||
@@ -210,51 +197,15 @@ export default function MatchDetail() {
|
||||
})}
|
||||
/>
|
||||
|
||||
{/* ── Full analysis toggle ── */}
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => setShowFullAnalysis(v => !v)}
|
||||
fullWidth
|
||||
endIcon={showFullAnalysis ? <ChevronUp size={15} /> : <ChevronDown size={15} />}
|
||||
sx={{
|
||||
borderStyle: 'dashed', color: DS_TEXT.muted, borderColor: DS_BORDER.strong,
|
||||
textTransform: 'none', fontWeight: 500,
|
||||
'&:hover': { borderColor: DS_TEXT.muted, bgcolor: DS_BG.subtle },
|
||||
}}
|
||||
>
|
||||
{showFullAnalysis ? 'Weniger anzeigen' : 'Vollständige Analyse anzeigen'}
|
||||
</Button>
|
||||
|
||||
{/* ── Full analysis (hidden by default) ── */}
|
||||
{showFullAnalysis && (
|
||||
<>
|
||||
<ExecutiveSummaryPanel match={match} />
|
||||
<NeedAlignmentPanel match={match} need={need} property={property} />
|
||||
{!isFuture && property && <MatchDetailPropertySections property={property} match={match} />}
|
||||
<LocationIntelligencePanel property={property} />
|
||||
{!isFuture && property?.images?.[0] && property?.location?.coordinates && (
|
||||
<Paper sx={{ overflow: 'hidden', p: 0 }}>
|
||||
<Box sx={{ px: 2.5, pt: 2, pb: 1 }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700 }}>Standort</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{property.address.street} {property.address.houseNumber}, {property.address.postalCode} {property.address.city}
|
||||
</Typography>
|
||||
</Box>
|
||||
<PropertyMap
|
||||
lat={property.location.coordinates.lat}
|
||||
lng={property.location.coordinates.lng}
|
||||
label={property.title}
|
||||
height={220}
|
||||
/>
|
||||
</Paper>
|
||||
)}
|
||||
<TradeoffPanel match={match} />
|
||||
<RiskPanel match={match} />
|
||||
<MissingInformationPanel match={match} />
|
||||
{isFuture && <FutureAvailabilityContextPanel match={match} signal={signal} />}
|
||||
<ScoreBreakdownPanel match={match} taxCalculatorUrl={taxCalculatorUrl} isFuture={isFuture} signal={signal} />
|
||||
</>
|
||||
)}
|
||||
{/* ── Full analysis toggle + expanded panels ── */}
|
||||
<MatchDetailScoreBreakdown
|
||||
match={match}
|
||||
property={property}
|
||||
need={need}
|
||||
signal={signal}
|
||||
isFuture={isFuture}
|
||||
taxCalculatorUrl={taxCalculatorUrl}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { memo, useState, useEffect, useCallback, useMemo } from 'react'
|
||||
import { useNavigate } from 'react-router'
|
||||
import {
|
||||
Alert, Box, Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle,
|
||||
Divider, FormControl, FormControlLabel, IconButton,
|
||||
Divider, FormControl, FormControlLabel,
|
||||
InputLabel, MenuItem, Select as MuiSelect,
|
||||
Skeleton, Switch, Tab, Tabs, TextField, ToggleButton, ToggleButtonGroup,
|
||||
Tooltip, Typography,
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function SupplyDashboard() {
|
||||
<Paper sx={{ p: 0, overflow: 'hidden', border: `1px solid ${DS_BORDER.default}` }}>
|
||||
|
||||
{/* KPI strip */}
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr 1fr', md: 'repeat(3, 1fr)' }, divideX: true }}>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr 1fr', md: 'repeat(3, 1fr)' } }}>
|
||||
{/* Starke Matches */}
|
||||
<Box sx={{ p: 2.5, borderRight: `1px solid ${DS_BORDER.default}`, bgcolor: strongMatchCount > 0 ? DS_SURFACE.success.bg : 'white' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75, mb: 0.5 }}>
|
||||
|
||||
Reference in New Issue
Block a user