From a3c7137b014bc2646aa1bfcf988ec42331c0350e Mon Sep 17 00:00:00 2001 From: Marko Djordjevic Date: Fri, 13 Feb 2026 00:14:53 +0100 Subject: [PATCH] feat: create ChartSelector component with dropdown, delete, and empty state --- .../changes/multi-chart-management/tasks.md | 6 +- src/components/ChartSelector.tsx | 120 ++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 src/components/ChartSelector.tsx diff --git a/openspec/changes/multi-chart-management/tasks.md b/openspec/changes/multi-chart-management/tasks.md index 007d567..1965e03 100644 --- a/openspec/changes/multi-chart-management/tasks.md +++ b/openspec/changes/multi-chart-management/tasks.md @@ -28,9 +28,9 @@ ## 5. Chart Selector UI Component -- [ ] 5.1 Create a `ChartSelector` component with dropdown listing all charts (name + created date), positioned in the sidebar between header and file upload -- [ ] 5.2 Add delete button per chart in the dropdown with confirmation dialog -- [ ] 5.3 Show "No charts — upload a CSV to get started" placeholder when no charts exist +- [x] 5.1 Create a `ChartSelector` component with dropdown listing all charts (name + created date), positioned in the sidebar between header and file upload +- [x] 5.2 Add delete button per chart in the dropdown with confirmation dialog +- [x] 5.3 Show "No charts — upload a CSV to get started" placeholder when no charts exist ## 6. Frontend State & Data Flow diff --git a/src/components/ChartSelector.tsx b/src/components/ChartSelector.tsx new file mode 100644 index 0000000..d48c6a7 --- /dev/null +++ b/src/components/ChartSelector.tsx @@ -0,0 +1,120 @@ +'use client'; + +import { useState } from 'react'; +import { ChevronDown, Trash2 } from 'lucide-react'; + +interface Chart { + id: number; + name: string; + created_at: number; +} + +interface ChartSelectorProps { + charts: Chart[]; + activeChartId: number | null; + onSelectChart: (chartId: number) => void; + onDeleteChart: (chartId: number) => void; +} + +export default function ChartSelector({ + charts, + activeChartId, + onSelectChart, + onDeleteChart, +}: ChartSelectorProps) { + const [isOpen, setIsOpen] = useState(false); + const [confirmDeleteId, setConfirmDeleteId] = useState(null); + + const activeChart = charts.find((c) => c.id === activeChartId); + + if (charts.length === 0) { + return ( +
+ No charts — upload a CSV to get started +
+ ); + } + + const formatDate = (timestamp: number) => { + return new Date(timestamp * 1000).toLocaleDateString(undefined, { + month: 'short', + day: 'numeric', + year: 'numeric', + }); + }; + + return ( +
+ + + {isOpen && ( +
+ {charts.map((chart) => ( +
+
{ + onSelectChart(chart.id); + setIsOpen(false); + }} + > +
{chart.name}
+
{formatDate(chart.created_at)}
+
+ +
+ ))} +
+ )} + + {/* Confirmation dialog */} + {confirmDeleteId !== null && ( +
+
+

+ Delete chart “{charts.find((c) => c.id === confirmDeleteId)?.name}” and all its candles and annotations? This cannot be undone. +

+
+ + +
+
+
+ )} +
+ ); +}