feat: full IDX universe (780 ticker) — universe table + close sweep harian, dashboard foreign-flow picker dari semua ticker, rotateDepth incremental fill 10/cylcle, strip .JK, backfill cmd/universe-sweep
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ async function req<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
}
|
||||
export interface Citation { endpoint: string; snapshot_at: string; ticker?: string; stale?: boolean }
|
||||
export interface Health { last_cycle_at: string; credits_today: number; scheduler_ok: boolean; stale_flags: string[] }
|
||||
export interface FlowSummary { date: string; foreign_net_total: number; top_accumulation: { ticker: string; net_sum: number; brokers: number }[]; closes: { ticker: string; close: number; date: string }[]; citations: Citation[] }
|
||||
export interface FlowSummary { date: string; foreign_net_total: number; top_accumulation: { ticker: string; net_sum: number; brokers: number }[]; closes: { ticker: string; close: number; date: string }[]; citations: Citation[]; foreign_tickers?: string[] }
|
||||
export interface ScreenRow { symbol: string; name: string; composite: number; breakdown: Record<string, unknown>; citations: Citation[] }
|
||||
export interface Routine { id: number; user_key: string; type: string; schedule_cron: string; channels_json?: string; channels?: string[]; enabled: boolean; last_run?: unknown }
|
||||
export interface AlertItem { id: number; user_key: string; name: string; rule_json: string; channels_json: string; last_fired: string }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createResource, createSignal, createMemo, For, Show } from "solid-js";
|
||||
import { createResource, createSignal, createEffect, For, Show } from "solid-js";
|
||||
import { A, useNavigate } from "@solidjs/router";
|
||||
import { api } from "../lib/api";
|
||||
import { useAuth } from "../components/auth";
|
||||
@@ -22,6 +22,13 @@ export default function Dashboard() {
|
||||
const [events] = createResource(me, (user) => (user ? api.alertEvents("2000-01-01").then((r) => r.events.slice(0, 5)).catch(() => []) : []));
|
||||
const [chartTiker, setChartTiker] = createSignal("BBCA");
|
||||
const [foreign] = createResource(chartTiker, (t) => api.flowForeign(t).catch(() => null));
|
||||
// Full picker list = every ticker that has foreign-flow rows.
|
||||
const fkTickers = () => flow()?.foreign_tickers || [];
|
||||
// Keep the current chart ticker valid even when the list changes.
|
||||
createEffect(() => {
|
||||
const list = fkTickers();
|
||||
if (list.length && !list.includes(chartTiker())) setChartTiker(list[0]);
|
||||
});
|
||||
|
||||
const ringkasan = () => {
|
||||
const n = briefing()?.narasi?.trim();
|
||||
@@ -124,7 +131,16 @@ export default function Dashboard() {
|
||||
<CardDescription><Term kata="foreign flow" /> harian — naik = asing beli, turun = asing jual. Pilih saham:</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="mb-3 flex flex-wrap gap-2">
|
||||
<div class="mb-3 flex flex-wrap items-center gap-2">
|
||||
<label class="sr-only" for="fk-ticker">Pilih saham</label>
|
||||
<select id="fk-ticker" class="h-9 rounded-md border bg-background px-2 text-sm"
|
||||
value={chartTiker()} onChange={(e) => setChartTiker((e.currentTarget as HTMLSelectElement).value)}>
|
||||
<For each={fkTickers()}>
|
||||
{(t) => <option value={t}>{t}</option>}
|
||||
</For>
|
||||
</select>
|
||||
<span class="text-xs text-muted-foreground">{fkTickers().length} saham tersedia</span>
|
||||
<span class="flex-1" />
|
||||
<For each={(flow()?.top_accumulation || []).map((t) => t.ticker)}>{(t) =>
|
||||
<Button size="sm" variant={chartTiker() === t ? "default" : "outline"} onClick={() => setChartTiker(t)}>{t}</Button>
|
||||
}</For>
|
||||
|
||||
Reference in New Issue
Block a user