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:
@@ -4,10 +4,13 @@ import { useEffect, useState } from "react";
|
||||
import { CandidateCard } from "../../components/CandidateCard";
|
||||
import { CandidateListItem } from "../../components/CandidateListItem";
|
||||
import { ComparisonTable } from "../../components/ComparisonTable";
|
||||
import { SetupImpactSelector } from "../../components/SetupImpactSelector";
|
||||
import {
|
||||
useReorderCandidates,
|
||||
useUpdateCandidate,
|
||||
} from "../../hooks/useCandidates";
|
||||
import { useImpactDeltas } from "../../hooks/useImpactDeltas";
|
||||
import { useSetup } from "../../hooks/useSetups";
|
||||
import { useThread } from "../../hooks/useThreads";
|
||||
import { LucideIcon } from "../../lib/iconData";
|
||||
import { useUIStore } from "../../stores/uiStore";
|
||||
@@ -23,8 +26,15 @@ function ThreadDetailPage() {
|
||||
const openCandidateAddPanel = useUIStore((s) => s.openCandidateAddPanel);
|
||||
const candidateViewMode = useUIStore((s) => s.candidateViewMode);
|
||||
const setCandidateViewMode = useUIStore((s) => s.setCandidateViewMode);
|
||||
const selectedSetupId = useUIStore((s) => s.selectedSetupId);
|
||||
const updateCandidate = useUpdateCandidate(threadId);
|
||||
const reorderMutation = useReorderCandidates(threadId);
|
||||
const { data: setupData } = useSetup(selectedSetupId);
|
||||
const { deltas } = useImpactDeltas(
|
||||
thread?.candidates ?? [],
|
||||
setupData?.items,
|
||||
thread?.categoryId ?? 0,
|
||||
);
|
||||
|
||||
const [tempItems, setTempItems] =
|
||||
useState<typeof thread extends { candidates: infer C } ? C : never | null>(
|
||||
@@ -120,7 +130,7 @@ function ThreadDetailPage() {
|
||||
)}
|
||||
|
||||
{/* Toolbar: Add candidate + view toggle */}
|
||||
<div className="mb-6 flex items-center gap-3">
|
||||
<div className="mb-6 flex items-center gap-3 flex-wrap">
|
||||
{isActive && candidateViewMode !== "compare" && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -185,6 +195,7 @@ function ThreadDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<SetupImpactSelector threadStatus={thread.status} />
|
||||
</div>
|
||||
|
||||
{/* Candidates */}
|
||||
@@ -208,6 +219,7 @@ function ThreadDetailPage() {
|
||||
<ComparisonTable
|
||||
candidates={displayItems}
|
||||
resolvedCandidateId={thread.resolvedCandidateId}
|
||||
deltas={deltas}
|
||||
/>
|
||||
) : candidateViewMode === "list" ? (
|
||||
isActive ? (
|
||||
@@ -230,6 +242,7 @@ function ThreadDetailPage() {
|
||||
status: newStatus,
|
||||
})
|
||||
}
|
||||
delta={deltas[candidate.id]}
|
||||
/>
|
||||
))}
|
||||
</Reorder.Group>
|
||||
@@ -247,6 +260,7 @@ function ThreadDetailPage() {
|
||||
status: newStatus,
|
||||
})
|
||||
}
|
||||
delta={deltas[candidate.id]}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -276,6 +290,7 @@ function ThreadDetailPage() {
|
||||
pros={candidate.pros}
|
||||
cons={candidate.cons}
|
||||
rank={index + 1}
|
||||
delta={deltas[candidate.id]}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user