UI: ensure dark text on job detail and job history cards (avoid white-on-light backgrounds)\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

This commit is contained in:
2026-05-16 15:13:38 +02:00
parent 3ed894015a
commit 329b83a17c
11 changed files with 1910 additions and 106 deletions
+24 -4
View File
@@ -14,21 +14,39 @@ interface ChartDataPoint {
interface TradingViewChartProps {
ticker: string;
data?: ChartDataPoint[];
timeframe?: string;
}
export default function TradingViewChart({ ticker, data }: TradingViewChartProps) {
const containerRef = useRef<HTMLDivElement>(null);
const TIMEFRAME_HEIGHTS: Record<string, number> = {
"1D": 300,
"5Min": 250,
"15Min": 250,
"1H": 350,
"1W": 400,
};
export default function TradingViewChart({ ticker, data, timeframe = "1D" }: TradingViewChartProps) {
const containerRef = useRef<HTMLDivElement>(null);
const height = TIMEFRAME_HEIGHTS[timeframe] ?? 400;
const isIntraday = ["1Min", "5Min", "15Min", "30Min", "1H"].includes(timeframe);
useEffect(() => {
if (!containerRef.current) {
return;
}
const chart = LightweightCharts.createChart(containerRef.current, {
height: 400,
height,
autoSize: true,
});
// Configure time scale based on timeframe and range
chart.timeScale().applyOptions({
timeVisible: isIntraday,
secondsVisible: timeframe === "1Min",
});
const candlestickSeries = chart.addSeries(LightweightCharts.CandlestickSeries, {
upColor: "#26a69a",
downColor: "#ef5350",
@@ -41,13 +59,15 @@ export default function TradingViewChart({ ticker, data }: TradingViewChartProps
if (data && data.length > 0) {
try {
candlestickSeries.setData(data as any);
// Fit the visible data range
chart.timeScale().fitContent();
} catch (err) {
console.error(`TradingViewChart: error setting data for ${ticker}`, err);
}
}
return () => chart.remove();
}, [data, ticker]);
}, [data, ticker, isIntraday, timeframe]);
return (
<div className="bg-white rounded-xl shadow-lg p-4">
+2 -2
View File
@@ -77,8 +77,8 @@ export async function action({ request }: { request: Request }) {
if (body.background) {
// Enqueue background analyze job and return 202 immediately
try {
const { enqueueAnalyze } = await import("../../lib/jobQueue");
const jobId = enqueueAnalyze(ticker, input);
const { enqueueAnalyze } = await import("../../lib/queue");
const jobId = await enqueueAnalyze(ticker, input);
return Response.json({ status: "queued", jobId }, { status: 202 });
} catch (enqueueErr) {
console.error("[analyze] enqueue error:", enqueueErr);
+2 -2
View File
@@ -53,7 +53,7 @@ export default function JobDetail() {
<Navbar />
<div className="mx-auto max-w-4xl px-6 py-8">
<h1 className="text-2xl font-bold text-gray-900 mb-4">Job {job?.id}</h1>
<div className="bg-white rounded-xl shadow-lg p-6 border border-gray-200">
<div className="bg-white rounded-xl shadow-lg p-6 border border-gray-200 text-gray-900">
<div className="mb-3 text-sm text-gray-700">State: <strong className="ml-2">{job?.state}</strong></div>
{job?.failedReason && (
<div className="mb-3 text-red-600">Failed: {job.failedReason}</div>
@@ -85,7 +85,7 @@ export default function JobDetail() {
</div>
<div className="text-sm text-gray-700 mb-3">Data:</div>
<pre className="bg-gray-50 p-3 rounded text-xs overflow-x-auto">{JSON.stringify(job?.data || job?.returnValue || job, null, 2)}</pre>
<pre className="bg-gray-50 p-3 rounded text-xs overflow-x-auto text-gray-800">{JSON.stringify(job?.data || job?.returnValue || job, null, 2)}</pre>
<div className="mt-4">