import { useState } from 'react' import { useQuery } from '@tanstack/react-query' import { apiFetch } from '@/lib/http' import { LoadingSkeleton } from '@/components/common/LoadingSkeleton' import { cn } from '@/lib/utils' interface Dependency { name: string type: 'service' | 'library' | 'infra' current_version: string latest_version: string breaking_change: boolean teams: string[] last_checked: string } interface DepResponse { dependencies: Dependency[] } async function fetchDeps(): Promise { const res = await apiFetch('/api/analytics/dependencies') return res.json() } type SortKey = 'name' | 'type' | 'breaking_change' function VersionBadge({ current, latest, breaking }: { current: string; latest: string; breaking: boolean }) { const upToDate = current === latest if (upToDate) { return ( up to date ) } return (
{current} {latest}
) } const TYPE_COLOURS: Record = { service: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400', library: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400', infra: 'bg-stone-100 text-stone-600 dark:bg-stone-800 dark:text-stone-300', } export function DependencyTracker() { const { data, isLoading } = useQuery({ queryKey: ['analytics-deps'], queryFn: fetchDeps, staleTime: 300_000, }) const [sort, setSort] = useState('breaking_change') const [filter, setFilter] = useState<'all' | 'outdated' | 'breaking'>('all') const deps = (data?.dependencies ?? []) .filter((d) => { if (filter === 'outdated') return d.current_version !== d.latest_version if (filter === 'breaking') return d.breaking_change return true }) .sort((a, b) => { if (sort === 'breaking_change') return (b.breaking_change ? 1 : 0) - (a.breaking_change ? 1 : 0) if (sort === 'type') return a.type.localeCompare(b.type) return a.name.localeCompare(b.name) }) const breakingCount = (data?.dependencies ?? []).filter((d) => d.breaking_change).length return (

Dependency Tracker

{breakingCount > 0 && (

{breakingCount} breaking change{breakingCount > 1 ? 's' : ''} require attention

)}
{/* Filter buttons */}
{(['all', 'outdated', 'breaking'] as const).map((f) => ( ))}
{/* Sort */}
{isLoading ? ( ) : deps.length === 0 ? (

No dependencies match this filter.

) : (
{deps.map((d) => ( ))}
Dependency Type Version Teams Checked
{d.breaking_change && ( )} {d.name}
{d.type} {d.teams.slice(0, 2).join(', ')}{d.teams.length > 2 ? ` +${d.teams.length - 2}` : ''} {new Date(d.last_checked).toLocaleDateString()}
)}
) }