refactor: premium design polish — cards, results, grid view
- PropertyIntelligenceCard: aspect-ratio image, hover animation, compact data-completeness row, tighter body padding - Results: replace verbose Card with compact active-search strip, remove DecisionContextPanel - Properties: add 3/5/10 column toggle in grid view, persist to localStorage - NeedInput, UnifiedResultCard/Feed, MatchCardViewModel: cleanup from earlier session Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,19 +43,26 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({
|
||||
<Box
|
||||
onClick={() => onSelect(p.id)}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
borderRadius: 2,
|
||||
overflow: 'hidden',
|
||||
border: `1px solid ${DS_BORDER.default}`,
|
||||
bgcolor: '#ffffff',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
cursor: 'pointer',
|
||||
transition: 'border-color 0.15s',
|
||||
'&:hover': { borderColor: '#c8c7c4' },
|
||||
position: 'relative',
|
||||
zIndex: 0,
|
||||
transition: 'transform 0.18s ease, box-shadow 0.18s ease, border-color 0.15s',
|
||||
'&:hover': {
|
||||
borderColor: '#b0aead',
|
||||
transform: 'scale(1.025)',
|
||||
boxShadow: '0 10px 32px rgba(0,0,0,0.13)',
|
||||
zIndex: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{/* ── Image — clean, no text overlay ── */}
|
||||
<Box sx={{ position: 'relative', height: 150, flexShrink: 0, bgcolor: '#f4f3f0', overflow: 'hidden' }}>
|
||||
<Box sx={{ position: 'relative', aspectRatio: '3/2', flexShrink: 0, bgcolor: '#f4f3f0', overflow: 'hidden' }}>
|
||||
{hasImage ? (
|
||||
<Box component="img" src={p.images![0]} alt={p.title}
|
||||
sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
|
||||
@@ -78,7 +85,7 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({
|
||||
</Box>
|
||||
|
||||
{/* ── Body ── */}
|
||||
<Box sx={{ px: 1.75, pt: 1.5, pb: 1.75, display: 'flex', flexDirection: 'column', gap: 1.125, flex: 1 }}>
|
||||
<Box sx={{ px: 2.25, pt: 1.75, pb: 2, display: 'flex', flexDirection: 'column', gap: 1.5, flex: 1 }}>
|
||||
|
||||
{/* Title + location + status inline */}
|
||||
<Box>
|
||||
@@ -130,36 +137,32 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
||||
{/* Property spec chips */}
|
||||
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>
|
||||
{p.hardFacts?.fitOut && (() => {
|
||||
const meta = FIT_OUT_META[p.hardFacts!.fitOut!] ?? { label: p.hardFacts!.fitOut!, tip: '' }
|
||||
return (
|
||||
<Tooltip title={meta.tip} placement="top" arrow>
|
||||
<Chip label={meta.label} size="small"
|
||||
sx={{ height: 20, fontSize: '0.68rem', bgcolor: '#f4f3f0', color: DS_TEXT.secondary, border: `1px solid ${DS_BORDER.default}`, cursor: 'help' }} />
|
||||
</Tooltip>
|
||||
)
|
||||
})()}
|
||||
{p.contractDurationMonths && (
|
||||
<Chip label={`${p.contractDurationMonths}M Vertrag`} size="small"
|
||||
sx={{ height: 20, fontSize: '0.68rem', bgcolor: '#f4f3f0', color: DS_TEXT.secondary, border: `1px solid ${DS_BORDER.default}` }} />
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Data completeness */}
|
||||
<Box sx={{ mt: 'auto' }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 0.5 }}>
|
||||
<Typography sx={{ fontSize: '0.62rem', color: DS_TEXT.disabled, letterSpacing: '0.03em' }}>
|
||||
Datenvollständigkeit
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: '0.75rem', fontWeight: 700, color: p.confidenceScore >= 0.75 ? '#b8975a' : DS_TEXT.muted }}>
|
||||
{/* Chips + Datenvollständigkeit in einer Zeile */}
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 1, mt: 'auto' }}>
|
||||
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', alignItems: 'center' }}>
|
||||
{p.hardFacts?.fitOut && (() => {
|
||||
const meta = FIT_OUT_META[p.hardFacts!.fitOut!] ?? { label: p.hardFacts!.fitOut!, tip: '' }
|
||||
return (
|
||||
<Tooltip title={meta.tip} placement="top" arrow>
|
||||
<Chip label={meta.label} size="small"
|
||||
sx={{ height: 20, fontSize: '0.68rem', bgcolor: '#f4f3f0', color: DS_TEXT.secondary, border: `1px solid ${DS_BORDER.default}`, cursor: 'help' }} />
|
||||
</Tooltip>
|
||||
)
|
||||
})()}
|
||||
{p.contractDurationMonths && (
|
||||
<Chip label={`${p.contractDurationMonths}M Vertrag`} size="small"
|
||||
sx={{ height: 20, fontSize: '0.68rem', bgcolor: '#f4f3f0', color: DS_TEXT.secondary, border: `1px solid ${DS_BORDER.default}` }} />
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75, flexShrink: 0 }}>
|
||||
<Typography sx={{ fontSize: '0.62rem', color: DS_TEXT.disabled }}>Daten</Typography>
|
||||
<LinearProgress variant="determinate" value={confPct}
|
||||
sx={{ width: 40, height: 3, borderRadius: 1, bgcolor: '#f4f3f0',
|
||||
'& .MuiLinearProgress-bar': { bgcolor: '#152642', borderRadius: 1 } }} />
|
||||
<Typography sx={{ fontSize: '0.72rem', fontWeight: 700, color: p.confidenceScore >= 0.75 ? '#b8975a' : DS_TEXT.muted }}>
|
||||
{confPct}%
|
||||
</Typography>
|
||||
</Box>
|
||||
<LinearProgress variant="determinate" value={confPct}
|
||||
sx={{ height: 3, borderRadius: 1, bgcolor: '#f4f3f0',
|
||||
'& .MuiLinearProgress-bar': { bgcolor: '#152642', borderRadius: 1 } }} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user