feat: add setup impact preview UI with delta badges across all views

Adds SetupImpactSelector dropdown and ImpactDeltaBadge inline badge, wired into the thread detail page. Delta badges appear on CandidateListItem, CandidateCard, and ComparisonTable (Weight Impact / Price Impact rows) whenever a setup is selected for comparison.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 18:11:57 +02:00
parent b9a06dd244
commit 8c1fe47a99
6 changed files with 153 additions and 1 deletions

View File

@@ -1,7 +1,9 @@
import { Reorder, useDragControls } from "framer-motion";
import { useFormatters } from "../hooks/useFormatters";
import type { CandidateDelta } from "../hooks/useImpactDeltas";
import { LucideIcon } from "../lib/iconData";
import { useUIStore } from "../stores/uiStore";
import { ImpactDeltaBadge } from "./ImpactDeltaBadge";
import { StatusBadge } from "./StatusBadge";
interface CandidateWithCategory {
@@ -28,6 +30,7 @@ interface CandidateListItemProps {
rank: number;
isActive: boolean;
onStatusChange: (status: "researching" | "ordered" | "arrived") => void;
delta?: CandidateDelta;
}
const RANK_COLORS = ["#D4AF37", "#C0C0C0", "#CD7F32"]; // gold, silver, bronze
@@ -49,6 +52,7 @@ export function CandidateListItem({
rank,
isActive,
onStatusChange,
delta,
}: CandidateListItemProps) {
const controls = useDragControls();
const { weight, price } = useFormatters();
@@ -111,11 +115,13 @@ export function CandidateListItem({
{weight(candidate.weightGrams)}
</span>
)}
<ImpactDeltaBadge delta={delta} type="weight" formatFn={weight} />
{candidate.priceCents != null && (
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-500">
{price(candidate.priceCents)}
</span>
)}
<ImpactDeltaBadge delta={delta} type="price" formatFn={price} />
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-50 text-gray-600">
<LucideIcon
name={candidate.categoryIcon}