Target selection syncs to chart; stable rail scale; sizing top-right
- 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:
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user