Files
property-match/src/pages/demand/Compare.tsx
T
Benjamin Sutter 5035445d2e refactor: standardize page title typography across all workspaces
All page-level headers now use fontSize:1.125rem, fontWeight:700,
color:#0f172a, container py:2.5, borderBottom:#e8e7e4 — matching
the standard established in PageHeader. Removes variant="h5"/h6"
inconsistencies across Supply, Demand, and shared components.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 00:01:15 +02:00

147 lines
4.9 KiB
TypeScript

import {
Alert,
Box,
Button,
Card,
Chip,
Stack,
Table,
TableCell,
TableHead,
TableRow,
Typography,
} from '@mui/material'
import { useNavigate } from 'react-router'
import { useCompareStore } from '../../stores/compareStore'
import {
CompareEmptyState,
CompareColumnHeader,
AICompareSummary,
CompareCriteriaCard,
CompareTableBody,
} from '../../components/compare'
import { AddToPipelineDialog } from '../../components/shortlist'
import {
LABEL_SX,
DATA_SX,
} from '../../components/compare/compareUtils'
import { useCompareData } from '../../hooks/useCompareData'
// ── Main component ────────────────────────────────────────────────────────────
export default function Compare() {
const navigate = useNavigate()
const { compareItems, removeFromCompare, clearCompare } = useCompareStore()
const {
aiSummary,
aiLoading,
activeNeed,
relevantCriteria,
overallWinnerIdx,
bestScoreIdx,
worstConfIdx,
worstDQIdx,
missingCriticalCounts,
maxMissingCritical,
} = useCompareData(compareItems)
if (compareItems.length === 0) {
return (
<Box>
<Box sx={{ bgcolor: 'white', borderBottom: '1px solid #e8e7e4', px: 3, py: 2.5 }}>
<Typography sx={{ fontWeight: 700, fontSize: '1.125rem', lineHeight: 1.3, color: '#0f172a' }}>Vergleich</Typography>
</Box>
<CompareEmptyState />
</Box>
)
}
return (
<Box>
<AddToPipelineDialog />
{/* Page header */}
<Box sx={{ bgcolor: 'white', borderBottom: '1px solid #e8e7e4', px: 3, py: 2.5, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<Typography sx={{ fontWeight: 700, fontSize: '1.125rem', lineHeight: 1.3, color: '#0f172a' }}>Vergleich</Typography>
<Chip label={`${compareItems.length} Ergebnisse`} size="small" />
</Box>
<Button variant="outlined" size="small" color="error" onClick={clearCompare}>
Vergleich leeren
</Button>
</Box>
{/* Mobile notice */}
<Box sx={{ display: { xs: 'block', md: 'none' }, p: 3 }}>
<Alert severity="info">
Die Vergleichsansicht ist für Desktop optimiert. Für beste Erfahrung auf einem grösseren Bildschirm öffnen.
</Alert>
</Box>
{/* Desktop table */}
<Box sx={{ display: { xs: 'none', md: 'block' }, px: 3, py: 3, pb: 10 }}>
{/* AI Summary */}
<AICompareSummary summary={aiSummary} isLoading={aiLoading && compareItems.length >= 2} />
{/* Criteria Head-to-Head */}
{activeNeed && relevantCriteria.length > 0 && (
<CompareCriteriaCard
compareItems={compareItems}
relevantCriteria={relevantCriteria}
overallWinnerIdx={overallWinnerIdx}
activeNeed={activeNeed}
/>
)}
<Card sx={{ overflowX: 'auto' }}>
<Table sx={{ tableLayout: 'auto' }}>
{/* Column headers */}
<TableHead>
<TableRow sx={{ bgcolor: '#f8fafc' }}>
<TableCell sx={{ ...LABEL_SX, bgcolor: '#f8fafc', zIndex: 2, fontSize: 11, color: '#64748b', fontWeight: 600 }}>
Kriterium
</TableCell>
{compareItems.map(item => (
<TableCell key={item.matchId} sx={{ ...DATA_SX, bgcolor: '#f8fafc', verticalAlign: 'top' }}>
<CompareColumnHeader item={item} onRemove={() => removeFromCompare(item.matchId)} />
</TableCell>
))}
</TableRow>
</TableHead>
<CompareTableBody
compareItems={compareItems}
bestScoreIdx={bestScoreIdx}
worstConfIdx={worstConfIdx}
worstDQIdx={worstDQIdx}
missingCriticalCounts={missingCriticalCounts}
maxMissingCritical={maxMissingCritical}
/>
</Table>
</Card>
{/* Add more prompt */}
{compareItems.length < 4 && (
<Card sx={{ p: 2.5, mt: 2, border: '2px dashed #e2e8f0', boxShadow: 'none' }}>
<Stack direction="row" sx={{ alignItems: 'center', justifyContent: 'space-between' }}>
<Box>
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>Weiteres Ergebnis hinzufügen</Typography>
<Typography variant="caption" color="text.secondary">
Bis zu {4 - compareItems.length} weitere{4 - compareItems.length === 1 ? 's' : ''} Ergebnis{4 - compareItems.length === 1 ? '' : 'se'} möglich
</Typography>
</Box>
<Button variant="outlined" size="small" onClick={() => navigate('/demand/results')}>
Zur Suche
</Button>
</Stack>
</Card>
)}
</Box>
</Box>
)
}