"use client"; import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; import { useToast } from "@/lib/toast"; import { COMPARE_METRICS, compareUrl, getWinnerIdx, overallScore, parseCompareSlugs, } from "@/lib/compareScore"; import { mergeDestinationsIntoTrip } from "@/lib/tripActions"; import { useI18n } from "@/lib/i18n"; import type { Destination } from "@/lib/types"; import RingNext from "@/components/RingNext"; import { useRingSteps } from "@/lib/rings"; interface Props { destinations: Destination[]; } export default function CompareClient({ destinations }: Props) { const searchParams = useSearchParams(); const router = useRouter(); const { toast } = useToast(); const { t } = useI18n(); const rings = useRingSteps(); const [picked, setPicked] = useState([]); useEffect(() => { const fromUrl = parseCompareSlugs(searchParams.get("cities")); if (fromUrl.length) { setPicked(fromUrl.filter((s) => destinations.some((d) => d.slug === s))); return; } setPicked([]); }, [searchParams, destinations]); const selected = useMemo( () => picked.map((s) => destinations.find((d) => d.slug === s)).filter((d): d is Destination => !!d), [picked, destinations] ); const scores = selected.map(overallScore); const winnerIdx = scores.length ? scores.indexOf(Math.max(...scores)) : -1; const syncUrl = (slugs: string[]) => { const href = compareUrl(slugs); router.replace(href, { scroll: false }); }; const toggle = (slug: string) => { setPicked((prev) => { let next: string[]; if (prev.includes(slug)) next = prev.filter((s) => s !== slug); else if (prev.length >= 4) { toast(t.compare.maxCities, "info"); return prev; } else next = [...prev, slug]; syncUrl(next); return next; }); }; const addAll = () => { if (selected.length < 1) return; const { added, skipped } = mergeDestinationsIntoTrip(selected, 1); if (added === 0) { toast(skipped ? t.compare.alreadyInPlan : t.compare.alreadyOne, "info"); router.push("/plan"); return; } toast(`${t.compare.addedN} ${added} ${t.compare.citiesUnit}${skipped ? `(${t.compare.skipped} ${skipped})` : ""}`); router.push("/plan"); }; const addWinner = () => { if (winnerIdx < 0) return; const d = selected[winnerIdx]; const { added } = mergeDestinationsIntoTrip([d], 1); toast(added ? `${d.emoji} ${d.name} ${t.compare.wrotePlan}` : t.compare.alreadyOne, added ? "success" : "info"); if (added) router.push("/plan"); }; const share = async () => { if (selected.length < 2) { toast(t.compare.needShare, "info"); return; } const url = `${window.location.origin}${compareUrl(selected.map((d) => d.slug))}`; await navigator.clipboard.writeText(url); toast(t.compare.linkCopied); }; return (
{t.compare.tag}

{t.compare.title}

{t.compare.subtitle}

{t.compare.pick}({picked.length}/4)

{destinations.map((d) => { const on = picked.includes(d.slug); return ( ); })}
{selected.length < 2 ? (
⚖️

{t.compare.needMore} {Math.max(0, 2 - selected.length)} {t.compare.needMoreSuffix}

{t.compare.backDest}
) : ( <>
{selected.map((d, i) => (
{i === winnerIdx && {t.compare.winner}} {d.emoji}

{d.name}

{d.country}
{scores[i]}
{t.common.detail}
))}
{COMPARE_METRICS.map((m) => { const values = selected.map(m.get); const winIdx = getWinnerIdx(values, m.lowerBetter); const maxVal = Math.max(...values); return (
{m.emoji} {m.label}
{selected.map((d, i) => { const val = m.get(d); const pct = maxVal > 0 ? (val / maxVal) * 100 : 0; return (
{d.emoji} {d.name} {i === winIdx && "🏆 "}{m.format(val)}
); })}
); })}
)}
); }