'use client'; import { Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Download, Plus, Share2, SlidersHorizontal, X } from 'lucide-react'; import { usePathname, useRouter } from 'next/navigation'; import { useCallback, useEffect, useRef, useState } from 'react'; import { t } from '@/i18n'; import { cn } from '@/lib/cn'; import { COMPARE_TABS, MAX_COMPARE_COUNTRIES, MIN_COMPARE_COUNTRIES, compareQuery, type CompareState, type CompareTab } from '@/lib/compare-state'; import { routes } from '@/lib/site'; import { COMPARE_UI_MODES, type CompareUiMode, type CountryLite } from '@/lib/types-compare'; import { seriesVar } from '@/components/charts/palette'; import { BottomSheet } from '@/components/data/bottom-sheet'; import { CountryPickerSheet } from './country-picker'; export const COMPARE_MIN_YEAR = 1960; /** * Sticky controls of /compare/[...slugs]: country chips (remove, reorder, add), view tabs and — for chart * tabs — year range, value mode, log toggle, CSV download and share. Every change is written to the URL * (`router.replace`, no scroll jump); country changes rewrite the path (`router.push`). */ export function CompareControls({ countries, allCountries, state, maxYear, downloadHref }: { countries: CountryLite[]; allCountries: CountryLite[]; state: CompareState; maxYear: number; downloadHref: string | null }) { const router = useRouter(); const pathname = usePathname(); const [picker, setPicker] = useState(false); const [options, setOptions] = useState(false); const [copied, setCopied] = useState(false); const [dragFrom, setDragFrom] = useState(null); const tabsRef = useRef(null); const slugs = countries.map((c) => c.slug); const exclude = new Set(slugs); const chartsTab = state.tab !== 'snapshot'; useEffect(() => { const el = tabsRef.current?.querySelector('[aria-selected="true"]'); el?.scrollIntoView({ block: 'nearest', inline: 'center', behavior: 'instant' as ScrollBehavior }); }, [state.tab]); const setState = useCallback( (patch: Partial) => { router.replace(`${pathname}${compareQuery({ ...state, ...patch })}`, { scroll: false }); }, [router, pathname, state], ); const setCountries = (next: string[]) => { router.push(`${routes.compare(...next)}${compareQuery(state)}`, { scroll: false }); }; const move = (from: number, to: number) => { if (to < 0 || to >= slugs.length || from === to) return; const next = [...slugs]; const [it] = next.splice(from, 1); next.splice(to, 0, it!); setCountries(next); }; const remove = (slug: string) => { if (slugs.length <= MIN_COMPARE_COUNTRIES) return; setCountries(slugs.filter((s) => s !== slug)); }; const add = (c: CountryLite) => { if (slugs.length >= MAX_COMPARE_COUNTRIES) return; setCountries([...slugs, c.slug]); }; const share = async () => { const url = window.location.href; try { if (navigator.share) { await navigator.share({ title: document.title, url }); return; } await navigator.clipboard.writeText(url); setCopied(true); setTimeout(() => setCopied(false), 1800); } catch { /* cancelled */ } }; const years: number[] = []; for (let y = maxYear; y >= COMPARE_MIN_YEAR; y--) years.push(y); const canRemove = slugs.length > MIN_COMPARE_COUNTRIES; const full = slugs.length >= MAX_COMPARE_COUNTRIES; const rangeAndMode = ( <>
{t('compare.range')}
{COMPARE_UI_MODES.map((m: CompareUiMode) => ( ))}
); const actions = ( <> {downloadHref ? ( {t('compare.download')} CSV ) : null} ); return (
{/* Row 1: country chips */}
    {countries.map((c, i) => (
  • setDragFrom(i)} onDragOver={(e) => e.preventDefault()} onDrop={() => { if (dragFrom != null) move(dragFrom, i); setDragFrom(null); }} onDragEnd={() => setDragFrom(null)} > {c.flag} {c.name}
  • ))}
{/* Row 2: tabs */}
{COMPARE_TABS.map((tab: CompareTab) => { const active = state.tab === tab; return ( ); })}
{/* Row 3 (md+): range · mode · log · download · share */}
{chartsTab ? rangeAndMode : null}
{actions}
setPicker(false)} countries={allCountries} exclude={exclude} onPick={add} /> setOptions(false)} side="center" title={t('compare.options')}>
{t('compare.legend')}
    {countries.map((c, i) => (
  1. {c.flag} {c.name}
  2. ))}
{chartsTab ? (
{t('compare.range')} · {t('compare.valueMode')}
{rangeAndMode}
) : null}
{actions}
); }