Target selection syncs to chart; stable rail scale; sizing top-right
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 1m4s
Deploy / deploy (push) Successful in 35s

- The ladder target choice is lifted to the ticker page (per
  direction), so selecting a target updates the candlestick overlay's
  target line and zone too, with the R:R for the tooltip taken from
  the ladder row.
- Price rail: the scale now always spans the entire target ladder, so
  stop / entry / now hold their positions and only the target marker
  moves when a different target is selected. The furthest target sits
  at the right edge.
- Setup card layout: position sizing (shares / value / max loss,
  details in the tooltip) and the Mark-as-taken button move to the top
  right of the card header row, next to the stats they belong with -
  the dangling bottom row is gone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 12:52:18 +02:00
co-authored by Claude Fable 5
parent 9f56a25f2d
commit 16121042cd
3 changed files with 89 additions and 39 deletions
+21 -1
View File
@@ -251,6 +251,13 @@ export default function TickerDetailPage() {
// Which setup the chart overlays. 'auto' = the ticker's preferred direction.
const [overlayChoice, setOverlayChoice] = useState<'auto' | 'long' | 'short' | 'none'>('auto');
// Target chosen in the recommendation ladder, per direction — the chart
// overlay follows it.
const [chosenTargets, setChosenTargets] = useState<{ long: number | null; short: number | null }>({
long: null,
short: null,
});
const action = (longSetup ?? shortSetup)?.recommended_action ?? null;
const overlaySetup: TradeSetup | undefined = useMemo(() => {
if (overlayChoice === 'none') return undefined;
@@ -263,6 +270,15 @@ export default function TickerDetailPage() {
return candidates.sort((a, b) => (b.confidence_score ?? 0) - (a.confidence_score ?? 0))[0];
}, [overlayChoice, longSetup, shortSetup, action]);
// Chart overlay with the ladder-selected target applied (R:R from the ladder).
const overlayWithTarget: TradeSetup | undefined = useMemo(() => {
if (!overlaySetup) return undefined;
const chosen = chosenTargets[overlaySetup.direction as 'long' | 'short'];
if (chosen == null || chosen === overlaySetup.target) return overlaySetup;
const ladder = overlaySetup.targets?.find((t) => t.price === chosen);
return { ...overlaySetup, target: chosen, rr_ratio: ladder?.rr_ratio ?? overlaySetup.rr_ratio };
}, [overlaySetup, chosenTargets]);
// Sort visible S/R levels by strength for the table (only levels within chart zones)
const sortedLevels = useMemo(() => {
if (!srLevels.data?.visible_levels) return [];
@@ -429,7 +445,7 @@ export default function TickerDetailPage() {
data={ohlcv.data}
srLevels={srLevels.data?.levels}
zones={srLevels.data?.zones}
tradeSetup={overlaySetup}
tradeSetup={overlayWithTarget}
currentPrice={priceInfo?.price}
/>
<p className="mt-2 text-[11px] text-gray-500">
@@ -447,6 +463,10 @@ export default function TickerDetailPage() {
shortSetup={shortSetup}
currentPrice={priceInfo?.price}
nextEarningsDate={fundamentals.data?.next_earnings_date}
selectedTargets={chosenTargets}
onSelectTarget={(direction, price) =>
setChosenTargets((s) => ({ ...s, [direction]: price }))
}
/>
</div>
)}