"use client"; import { useState } from "react"; import type { FactorContribution, ScoreGroupTotal } from "@/types/site-finder"; interface Props { topPositives: FactorContribution[]; topNegatives: FactorContribution[]; byGroup: ScoreGroupTotal[]; detailed: FactorContribution[]; } // Цвета stacked bar — соответствуют тематическим эшелонам const GROUP_COLORS: Record = { Социалка: "#0ea5e9", Торговля: "#a855f7", Парки: "#16a34a", Транспорт: "#eab308", "Шум/трамвай": "#dc2626", Локация: "#1d4ed8", Прочее: "#94a3b8", }; function fmtContribution(v: number): string { const sign = v >= 0 ? "+" : "−"; return `${sign}${Math.abs(v).toFixed(2)}`; } export function ScoreBreakdownPanel({ topPositives, topNegatives, byGroup, detailed, }: Props) { const [expanded, setExpanded] = useState(false); // Stacked bar — только positive groups (для визуальной шкалы вклада) const positiveGroups = byGroup.filter((g) => g.contribution > 0); const totalPositive = positiveGroups.reduce((s, g) => s + g.contribution, 0) || 1; return (
Почему такой балл
{/* Stacked bar — % contribution по группам */} {positiveGroups.length > 0 && (
{positiveGroups.map((g) => { const widthPct = (g.contribution / totalPositive) * 100; return (
{widthPct >= 10 ? `${Math.round(widthPct)}%` : ""}
); })}
{/* Positive groups — visible в баре */} {positiveGroups.map((g) => (
{g.group}:{" "} {fmtContribution(g.contribution)}
))}
{/* Negative groups — отдельной "drag" линией под баром (legend для bar использует только positive, чтобы не было orphan swatches без сегмента) */} {byGroup .filter((g) => g.contribution < 0) .map((g) => (
Снижают балл — {g.group}:{" "} {fmtContribution(g.contribution)}
))}
)} {/* Top-3 positive */} {topPositives.length > 0 && (
Топ-3 плюса
    {topPositives.map((f) => (
  • {f.verbal}
  • ))}
)} {/* Top-3 negative */} {topNegatives.length > 0 && (
Топ-3 минуса
    {topNegatives.map((f) => (
  • {f.verbal}
  • ))}
)} {/* Toggle full breakdown */} {detailed.length > 0 && (
{expanded && (
{detailed.map((f) => ( ))}
Фактор Вклад %
{f.verbal} = 0 ? "#16a34a" : "#dc2626", fontVariantNumeric: "tabular-nums", fontWeight: 600, }} > {fmtContribution(f.contribution)} {f.contribution_pct.toFixed(1)}%
)}
)}
); }