import { MainLayout } from '@/components/layout/MainLayout.tsx'; import PageHeader from '@/components/layout/PageHeader.tsx'; import { useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; // Imports trimmed: unused components removed import Badge from '@/components/ui/Badge.tsx'; import Button from '@/components/ui/Button.tsx'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card.tsx'; import Input from '@/components/ui/Input.tsx'; import { Container, Flex, Grid, Stack } from '@/components/ui/layout'; import Select from '@/components/ui/Select.tsx'; import { useFindMatches, useTopMatches } from '@/hooks/api/useMatchingAPI.ts'; import { useTranslation } from '@/hooks/useI18n.tsx'; import { useNavigation } from '@/hooks/useNavigation.tsx'; import { useOrganizations } from '@/hooks/useOrganizations.ts'; import { Plus, Target, TrendingUp } from 'lucide-react'; const MatchingDashboard = () => { const { t } = useTranslation(); const navigate = useNavigate(); const { handleBackNavigation, handleFooterNavigate } = useNavigation(); const { organizations } = useOrganizations(); // Search state const [searchQuery, setSearchQuery] = useState(''); const [selectedOrgId, setSelectedOrgId] = useState(''); const [maxDistance, setMaxDistance] = useState(50); const [minScore, setMinScore] = useState(0.6); // Get top matches for overview const { data: topMatches, isLoading: isLoadingTop } = useTopMatches(20); // Get matches based on search criteria const searchResourceId = searchQuery ? searchQuery : undefined; const { data: searchMatches, isLoading: isLoadingSearch } = useFindMatches( searchResourceId, searchResourceId ? { max_distance_km: maxDistance, min_score: minScore, limit: 20, } : undefined ); // Calculate statistics const stats = useMemo(() => { if (!topMatches?.matches) return { total: 0, highScore: 0, avgDistance: 0 }; const matches = topMatches.matches; const total = matches.length; const highScore = matches.filter((m) => m.overall_score >= 0.8).length; const avgDistance = matches.length > 0 ? matches.reduce((sum, m) => sum + m.distance_km, 0) / matches.length : 0; return { total, highScore, avgDistance: Math.round(avgDistance * 10) / 10 }; }, [topMatches]); const handleViewMatch = (matchId: string) => { navigate(`/matching/${matchId}`); }; const handleCreateResourceFlow = () => { navigate('/resources'); }; const organizationOptions = useMemo(() => { return ( organizations?.map((org) => ({ value: org.ID, label: org.Name, })) || [] ); }, [organizations]); const currentMatches = searchQuery ? searchMatches : topMatches; return ( {/* Statistics Cards */} {t('matchingDashboard.totalMatches')}
{stats.total}

{t('matchingDashboard.activeMatches')}

{t('matchingDashboard.highQuality')}
{stats.highScore}

{t('matchingDashboard.scoreAbove80')}

📍 {t('matchingDashboard.avgDistance')}
{stats.avgDistance} {t('common.km')}

{t('matchingDashboard.withinRange')}

{/* Search and Filters */} {t('matchingDashboard.findMatches')}
setSearchQuery(e.target.value)} />
setMaxDistance(Number(e.target.value))} />
setMinScore(Number(e.target.value))} />
{/* Results */} {currentMatches && ( {searchQuery ? t('matchingDashboard.searchResults') : t('matchingDashboard.topMatches')} {currentMatches.matches.length > 0 && ( {currentMatches.matches.length} {t('matchingDashboard.matches')} )} {isLoadingTop || isLoadingSearch ? (
) : currentMatches.matches.length > 0 ? (
{currentMatches.matches.slice(0, 10).map((match) => (
handleViewMatch(match.ID)} >

{t('matchingDashboard.sourceFlow')}

{match.source_flow?.type} ({match.source_flow?.direction})

{t('matchingDashboard.targetFlow')}

{match.target_flow?.type} ({match.target_flow?.direction})

= 0.8 ? 'default' : 'secondary'}> {Math.round(match.overall_score * 100)}% {match.distance_km?.toFixed(1)} {t('common.km')}
))} {currentMatches.matches.length > 10 && (
)}
) : (

{searchQuery ? t('matchingDashboard.noSearchResults') : t('matchingDashboard.noMatchesFound')}

{!searchQuery && ( )}
)}
)} {/* Quick Actions */} {t('matchingDashboard.quickActions')}
); }; export default MatchingDashboard;