feat: replace arrowDown markers with ★ stars overlay on chart, colored by category
- InstrumentChart: remove setMarkers arrowDown (level-colored) Add DOM overlay div with ★ HTML characters positioned via timeToCoordinate + priceToCoordinate(candle.high) - 52px; sized by impact_score; colored by category Label (title, 22 chars) rendered above each star; redrawn on scroll/zoom via subscribeVisibleLogicalRangeChange; cleaned up on unmount ChartEvent interface: add category, impact_score, end_date, description Header legend: replace ▼ LT/MT/CT with ★ category color legend - InstrumentDashboard: remove EventStarsStrip (now internal to chart) Remove unused dateToMs helper Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -109,8 +109,6 @@ function fmtDateFR(s: string | null): string {
|
||||
return `${d}/${m}/${y}`
|
||||
}
|
||||
|
||||
function dateToMs(s: string) { return new Date(s).getTime() }
|
||||
|
||||
function pctN(a: number | undefined, b: number | undefined): number {
|
||||
if (a === undefined || b === undefined || b === 0) return 0
|
||||
return ((a - b) / b) * 100
|
||||
@@ -507,63 +505,6 @@ function NarrativeCard({ narrative, loading, onLoad, instrument }: {
|
||||
)
|
||||
}
|
||||
|
||||
// ── EventStarsStrip — étoiles au-dessus du graphe ────────────────────────────
|
||||
|
||||
const CAT_STAR_COLORS: Record<string, string> = {
|
||||
event_calendar: '#f59e0b', // amber
|
||||
geopolitical: '#ef4444', // red
|
||||
fundamental: '#10b981', // emerald
|
||||
report: '#3b82f6', // blue
|
||||
sentiment: '#8b5cf6', // violet
|
||||
technical: '#06b6d4', // cyan
|
||||
}
|
||||
|
||||
function EventStarsStrip({
|
||||
events, priceData,
|
||||
}: {
|
||||
events: SnapshotEvent[]
|
||||
priceData: PriceCandle[]
|
||||
}) {
|
||||
if (priceData.length < 2 || events.length === 0) return null
|
||||
|
||||
const chartStart = dateToMs(priceData[0].time)
|
||||
const chartEnd = dateToMs(priceData[priceData.length - 1].time)
|
||||
const totalMs = chartEnd - chartStart
|
||||
if (totalMs <= 0) return null
|
||||
|
||||
function leftPct(d: string) {
|
||||
return Math.max(0.5, Math.min(98.5, ((dateToMs(d) - chartStart) / totalMs) * 100))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative" style={{ height: 28, paddingRight: 62 }}>
|
||||
{events.map((ev, i) => {
|
||||
const left = leftPct(ev.date)
|
||||
const color = CAT_STAR_COLORS[ev.category] ?? '#94a3b8'
|
||||
const score = ev.impact_score ?? 0.5
|
||||
const size = score >= 0.8 ? 16 : score >= 0.6 ? 13 : 11
|
||||
return (
|
||||
<span
|
||||
key={i}
|
||||
className="absolute -translate-x-1/2 select-none cursor-default transition-transform hover:scale-150"
|
||||
style={{
|
||||
left: `${left}%`,
|
||||
bottom: 2,
|
||||
fontSize: size,
|
||||
color,
|
||||
lineHeight: 1,
|
||||
filter: `drop-shadow(0 0 3px ${color}60)`,
|
||||
}}
|
||||
title={`${ev.title}\n${ev.date}${ev.end_date ? ' → ' + ev.end_date : ''}\n${ev.description ?? ''}`}
|
||||
>
|
||||
★
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ── DriversPanel — édition inline ────────────────────────────────────────────
|
||||
|
||||
function DriversPanel({ instrumentId, drivers, onSave, onClose }: {
|
||||
@@ -915,11 +856,6 @@ export default function InstrumentDashboard() {
|
||||
{/* ── Content ── */}
|
||||
{!loading && snapshot && (
|
||||
<>
|
||||
<EventStarsStrip
|
||||
events={snapshot.events}
|
||||
priceData={snapshot.price_data}
|
||||
/>
|
||||
|
||||
<InstrumentChart
|
||||
priceData={snapshot.price_data}
|
||||
indicators={snapshot.indicators}
|
||||
|
||||
Reference in New Issue
Block a user