mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Remove unused imports and variables from DashboardPage, HeritageBuildingPage, MatchesMapView - Fix i18n literal strings in NetworkGraph component - Continue systematic reduction of linting errors
109 lines
3.7 KiB
TypeScript
109 lines
3.7 KiB
TypeScript
import Badge from '@/components/ui/Badge';
|
|
import { Card } from '@/components/ui/Card';
|
|
import { Flex, Grid, Stack } from '@/components/ui/layout';
|
|
import { useTranslation } from '@/hooks/useI18n';
|
|
import type { BackendMatch } from '@/schemas/backend/match';
|
|
import { AlertTriangle, MapPin, TrendingUp } from 'lucide-react';
|
|
import React from 'react';
|
|
import { formatCurrency } from '../../lib/fin';
|
|
|
|
interface MatchCardProps {
|
|
match: BackendMatch;
|
|
onViewDetails?: (matchId: string) => void;
|
|
}
|
|
|
|
const MatchCard: React.FC<MatchCardProps> = ({ match, onViewDetails }) => {
|
|
const { t } = useTranslation();
|
|
|
|
const getStatusColor = () => {
|
|
switch (match.Status) {
|
|
case 'suggested':
|
|
return 'default';
|
|
case 'negotiating':
|
|
return 'outline';
|
|
case 'contracted':
|
|
case 'live':
|
|
return 'default';
|
|
case 'failed':
|
|
case 'cancelled':
|
|
return 'destructive';
|
|
default:
|
|
return 'outline';
|
|
}
|
|
};
|
|
|
|
const formatScore = (score: number) => {
|
|
return `${(score * 100).toFixed(0)}%`;
|
|
};
|
|
|
|
// use central fin utilities
|
|
|
|
return (
|
|
<Card
|
|
className="shadow-none hover:shadow-md transition-shadow cursor-pointer"
|
|
onClick={() => onViewDetails?.(match.ID)}
|
|
>
|
|
<Stack spacing="sm" className="p-4">
|
|
<Flex align="start" justify="between">
|
|
<div className="flex-1">
|
|
<Flex align="center" gap="xs" className="mb-2">
|
|
<Badge variant={getStatusColor()}>{match.Status}</Badge>
|
|
<Badge variant="outline" className="text-xs">
|
|
{t('matches.priority', { priority: match.Priority })}
|
|
</Badge>
|
|
</Flex>
|
|
|
|
<Grid cols={2} gap="md" className="mb-3">
|
|
<div>
|
|
<p className="text-xs text-muted-foreground mb-1">{t('matches.compatibility')}</p>
|
|
<p className="text-lg font-semibold">{formatScore(match.CompatibilityScore)}</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-xs text-muted-foreground mb-1">{t('matches.economicValue')}</p>
|
|
<p className="text-lg font-semibold text-success">
|
|
{formatCurrency(match.EconomicValue)}
|
|
</p>
|
|
</div>
|
|
</Grid>
|
|
|
|
<Flex align="center" gap="md" className="text-sm text-muted-foreground">
|
|
<div className="flex items-center gap-1">
|
|
<MapPin className="h-4 w-4" />
|
|
<span>{t('matches.distance', { distance: match.DistanceKm.toFixed(1) })}</span>
|
|
</div>
|
|
{match.RiskAssessment && (
|
|
<div className="flex items-center gap-1">
|
|
<AlertTriangle className="h-4 w-4" />
|
|
<span>
|
|
{t('matches.riskScore', {
|
|
score: formatScore(
|
|
(match.RiskAssessment.technical_risk +
|
|
match.RiskAssessment.regulatory_risk) /
|
|
2
|
|
),
|
|
})}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</Flex>
|
|
|
|
{match.EconomicImpact && match.EconomicImpact.annual_savings && (
|
|
<div className="mt-3 pt-3 border-t">
|
|
<Flex align="center" gap="xs" className="text-sm">
|
|
<TrendingUp className="h-4 w-4 text-success" />
|
|
<span className="text-muted-foreground">{t('matches.annualSavings')}:</span>
|
|
<span className="font-semibold text-success">
|
|
{formatCurrency(match.EconomicImpact.annual_savings)}
|
|
</span>
|
|
</Flex>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Flex>
|
|
</Stack>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
export default React.memo(MatchCard);
|