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>
40 lines
893 B
TypeScript
40 lines
893 B
TypeScript
import type { CandidateDelta } from "../hooks/useImpactDeltas";
|
|
|
|
interface ImpactDeltaBadgeProps {
|
|
delta: CandidateDelta | undefined;
|
|
type: "weight" | "price";
|
|
formatFn: (value: number) => string;
|
|
}
|
|
|
|
export function ImpactDeltaBadge({
|
|
delta,
|
|
type,
|
|
formatFn,
|
|
}: ImpactDeltaBadgeProps) {
|
|
if (!delta || delta.mode === "none") return null;
|
|
|
|
const value = type === "weight" ? delta.weightDelta : delta.priceDelta;
|
|
|
|
if (value === null) {
|
|
return <span className="text-xs text-gray-400">—</span>;
|
|
}
|
|
|
|
if (value === 0) {
|
|
return <span className="text-xs text-gray-400">±0</span>;
|
|
}
|
|
|
|
if (value > 0) {
|
|
return (
|
|
<span className="text-xs text-green-600">
|
|
+{formatFn(value)}
|
|
{delta.mode === "add" && (
|
|
<span className="ml-0.5 text-green-500">(add)</span>
|
|
)}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
// value < 0
|
|
return <span className="text-xs text-red-500">{formatFn(value)}</span>;
|
|
}
|