Commit graph

210 commits

Author SHA1 Message Date
Marko Djordjevic
09a361ca54 code-review-fix task 15.3: mark task 15.3 as done in tasks.md 2026-02-18 20:58:18 +01:00
Marko Djordjevic
9c08ffc44d code-review-fix task 15.2: mark task 15.2 as done in tasks.md 2026-02-18 20:57:44 +01:00
Marko Djordjevic
728c7e4d82 code-review-fix task 15.1: mark task 15.1 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:57:13 +01:00
Marko Djordjevic
21c855db89 code-review-fix task 14.5: mark task 14.5 as done in tasks.md 2026-02-18 20:55:21 +01:00
Marko Djordjevic
d4c14df284 code-review-fix task 14.4: mark task 14.4 as done in tasks.md 2026-02-18 20:48:44 +01:00
Marko Djordjevic
3e4d4bd7ae code-review-fix task 14.3: mark task 14.3 as done in tasks.md 2026-02-18 20:48:14 +01:00
Marko Djordjevic
4081a566b5 code-review-fix task 14.2: mark task 14.2 as done in tasks.md 2026-02-18 20:47:51 +01:00
Marko Djordjevic
c9c63aafa3 code-review-fix task 14.1: mark task 14.1 as done in tasks.md 2026-02-18 20:47:17 +01:00
Marko Djordjevic
bf9a475b89 code-review-fix task 13.3: mark task 13.3 as done in tasks.md 2026-02-18 20:46:37 +01:00
Marko Djordjevic
03b2500980 code-review-fix task 13.2: mark task 13.2 as done in tasks.md 2026-02-18 20:46:04 +01:00
Marko Djordjevic
36382508f7 code-review-fix task 13.1: mark task 13.1 as done in tasks.md 2026-02-18 20:45:30 +01:00
Marko Djordjevic
576375b135 code-review-fix task 12.12: mark task 12.12 as done in tasks.md 2026-02-18 20:44:54 +01:00
Marko Djordjevic
5ffab3ef44 code-review-fix task 12.11: mark task 12.11 as done in tasks.md 2026-02-18 20:44:04 +01:00
Marko Djordjevic
13f4860358 code-review-fix task 12.10: mark task 12.10 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:43:25 +01:00
Marko Djordjevic
030b0c5885 code-review-fix task 12.9: mark task 12.9 as done in tasks.md 2026-02-18 20:42:17 +01:00
Marko Djordjevic
3f6bcd5c7d code-review-fix task 12.8: mark task 12.8 as done in tasks.md 2026-02-18 20:40:47 +01:00
Marko Djordjevic
2d8222740c code-review-fix task 12.7: mark task 12.7 as done in tasks.md 2026-02-18 20:40:08 +01:00
Marko Djordjevic
e8b8bbb56f code-review-fix task 12.6: mark task 12.6 as done in tasks.md 2026-02-18 20:39:14 +01:00
Marko Djordjevic
6260f7caed code-review-fix task 12.5: mark task 12.5 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:38:30 +01:00
Marko Djordjevic
f9ff0d266e code-review-fix task 12.4: mark task 12.4 as done in tasks.md 2026-02-18 20:37:40 +01:00
Marko Djordjevic
a0a30beb8e code-review-fix task 12.3: mark task 12.3 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:36:41 +01:00
Marko Djordjevic
6a194e81ac code-review-fix task 12.2: mark task 12.2 as done in tasks.md 2026-02-18 20:34:55 +01:00
Marko Djordjevic
15be4c6ca1 code-review-fix task 12.1: mark task 12.1 as done in tasks.md 2026-02-18 20:34:20 +01:00
Marko Djordjevic
d1e992bc79 code-review-fix task 11.4: mark task 11.4 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:33:52 +01:00
Marko Djordjevic
49a2582e8a code-review-fix task 11.3: mark task 11.3 as done in tasks.md 2026-02-18 20:32:25 +01:00
Marko Djordjevic
3793e646cb code-review-fix task 11.2: mark task 11.2 as done in tasks.md 2026-02-18 20:31:30 +01:00
Marko Djordjevic
6f7e3451a2 code-review-fix task 11.1: mark task 11.1 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:30:37 +01:00
Marko Djordjevic
e5ce5cb2e4 code-review-fix task 10.4: mark task 10.4 as done in tasks.md 2026-02-18 20:29:32 +01:00
Marko Djordjevic
bd57bb13e4 code-review-fix task 10.3: mark task 10.3 as done in tasks.md 2026-02-18 20:28:57 +01:00
Marko Djordjevic
ed05bd6972 code-review-fix task 10.2: mark task 10.2 as done in tasks.md 2026-02-18 20:27:36 +01:00
Marko Djordjevic
4bd9d6f9da code-review-fix task 10.1: mark task 10.1 as done in tasks.md 2026-02-18 20:27:05 +01:00
Marko Djordjevic
43b6b5da9e code-review-fix task 9.8: mark task 9.8 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 20:26:05 +01:00
Marko Djordjevic
1b637dc45e task 9.7: mark task 9.7 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:49:43 +01:00
Marko Djordjevic
28a0d0790e task 9.6: mark task 9.6 as completed in tasks.md 2026-02-18 15:46:06 +01:00
Marko Djordjevic
2be91ceea8 task 9.5: mark task 9.5 as complete in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:45:36 +01:00
Marko Djordjevic
76c440d879 task 9.4: mark task 9.4 as done in tasks.md
src/types/predictions.ts already existed with PredictionSpan, PredictionState, and ModelInfoResponse interfaces matching actual usage across page.tsx, CandleChart.tsx, and PredictionPanel.tsx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:44:24 +01:00
Marko Djordjevic
a7087ef945 task 9.3: mark task 9.3 as done in tasks.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:43:36 +01:00
Marko Djordjevic
f05a0081f7 feat: add shared Annotation, AnnotationType, Geometry interfaces in src/types/annotations.ts
Creates src/types/annotations.ts with typed interfaces matching actual
usage in CandleChart.tsx, page.tsx, and DB schema. Marks task 9.2 done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:27:13 +01:00
Marko Djordjevic
8b40a2cb9a feat: create src/types/candles.ts with Candle interface (task 9.1)
Add shared Candle interface with time, open, high, low, close, and
optional volume fields. Volume is optional because the DB schema does
not store volume but the predict/patterns API routes accept it as an
optional field.

Mark task 9.1 as complete in tasks.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:26:14 +01:00
Marko Djordjevic
90d62cf187 chore: mark task 8.8 as completed 2026-02-18 15:25:23 +01:00
Marko Djordjevic
2f1e4944de Mark task 8.7 as completed - Extract magic numbers to named constants
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:24:41 +01:00
Marko Djordjevic
d6d844a003 fix: detect candle interval dynamically instead of hardcoded 60s
Replace the hardcoded 60-second assumption in CandleChart.tsx with
dynamic interval detection: compute interval as candles[1].time -
candles[0].time when at least 2 candles are available, fall back to
60 otherwise. Used for span-to-prediction-time mapping iteration.

Marks task 8.6 as done in tasks.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:23:11 +01:00
Marko Djordjevic
8395f23744 feat: add bounded prediction cache (max 100 entries, FIFO eviction)
- Before inserting into predictionCacheRef, check if size >= 100
- If so, evict oldest entry via cache.keys().next().value (FIFO)
- Applied at both cache write sites (lines ~549 and ~671 in page.tsx)
- Marks task 8.5 as done in tasks.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:22:38 +01:00
Marko Djordjevic
acf31d3edf perf: split SpanAnnotationManager reconciliation into two effects
Separate the single reconciliation effect into:
1. Full reconciliation effect — runs only when spanAnnotations list,
   series, chart, or candles change. Rebuilds all primitives.
2. Selection-only effect — runs only when selectedSpanId changes.
   Calls setSelected() on existing primitives instead of detaching
   and reattaching all of them.

This avoids tearing down and rebuilding every primitive on each
selection change, which was the main unnecessary overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:21:46 +01:00
Marko Djordjevic
aa27fe93f6 perf: remove fitContent() from reconciliation effect, call only on initial load
Move chart.timeScale().fitContent() out of the span annotation reconciliation
effect (which ran on every annotation/selection change) into a dedicated effect
guarded by a hasInitializedRef, so it fires only once when chart and series
first become available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:20:37 +01:00
Marko Djordjevic
131d2912d5 fix: use chart.applyOptions() for theme changes instead of re-creating chart
Remove resolvedTheme from the chart initialization useEffect dependency
array so theme changes no longer destroy and re-create the entire chart.
Add a separate useEffect that calls chartRef.current.applyOptions() with
the new layout, grid, timeScale and rightPriceScale colors whenever
resolvedTheme changes, avoiding the memory leak and flicker caused by
full chart reconstruction on every theme toggle.

Closes task 8.2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:19:44 +01:00
Marko Djordjevic
0cd7a34c99 fix: replace useState with useRef for preview primitive to prevent memory leak
The preview primitive in SpanAnnotationManager was stored in useState,
causing unnecessary re-renders and potential memory leaks since the
primitive was not cleaned up on unmount. Changed to useRef, updated all
read/write sites, removed from dependency arrays, and added unmount
cleanup effect that detaches the primitive from the series.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:18:48 +01:00
Marko Djordjevic
e5b0cc2540 fix: resolve stale closure in SpanAnnotationManager keyboard handler
Use selectedSpanIdRef to avoid capturing stale selectedSpanId in the
keyboard event handler closure. Wrap handleDeleteSpan in useCallback
with stable dependencies (reads selectedSpanIdRef.current instead of
the prop directly). Remove selectedSpanId from the useEffect dependency
array since the ref is used instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:16:55 +01:00
Marko Djordjevic
73c88f8211 fix: resolve stale closures in CandleChart click handler
Convert drawingState, selectedLineId, dragState, and annotations to
refs that stay in sync with state via useEffect. The chart click handler
(subscribeClick) captured stale closure values for these variables.
Now reads from refs (e.g. drawingStateRef.current) so the handler
always sees the latest state, and removed the stale state variables
from the useEffect dependency array.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:15:24 +01:00
Marko Djordjevic
45a23047dd fix: add AbortController to fetchPredictions and handleFetchBatchPredictions
Prevent race conditions by aborting in-flight requests when a new
request is triggered. Each function now:
- Aborts the previous request via a stored AbortController ref
- Passes signal to all fetch() calls
- Silently discards AbortError in catch blocks

Completes task 7.2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:12:40 +01:00