diff --git a/src/app/page.tsx b/src/app/page.tsx index ab944f6..c53be91 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,10 +1,45 @@ +'use client'; + +import { useState } from 'react'; +import Toolbox, { Tool } from '@/components/Toolbox'; +import FileUpload from '@/components/FileUpload'; + export default function Home() { + const [activeTool, setActiveTool] = useState(null); + + const handleExport = () => { + window.location.href = '/api/export'; + }; + + const handleUploadSuccess = () => { + // TODO: Trigger chart refresh + console.log('Upload successful - refresh chart'); + }; + return ( -
-

Candle Annotator

-

- Upload CSV data and annotate candlestick charts -

-
+
+ {/* Sidebar */} + + + {/* Main chart area */} +
+
+

Upload a CSV file to view the candlestick chart

+

CSV format: time, open, high, low, close

+
+
+
); } diff --git a/src/components/FileUpload.tsx b/src/components/FileUpload.tsx new file mode 100644 index 0000000..5c7914c --- /dev/null +++ b/src/components/FileUpload.tsx @@ -0,0 +1,98 @@ +'use client'; + +import { useState, useRef } from 'react'; +import { Button } from '@/components/ui/button'; +import { Upload } from 'lucide-react'; + +interface FileUploadProps { + onUploadSuccess: () => void; +} + +export default function FileUpload({ onUploadSuccess }: FileUploadProps) { + const [isUploading, setIsUploading] = useState(false); + const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); + const fileInputRef = useRef(null); + + const handleFileChange = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + setIsUploading(true); + setMessage(null); + + const formData = new FormData(); + formData.append('file', file); + + try { + const response = await fetch('/api/upload', { + method: 'POST', + body: formData, + }); + + const data = await response.json(); + + if (response.ok) { + setMessage({ + type: 'success', + text: `Successfully uploaded ${data.count} candle records`, + }); + onUploadSuccess(); + } else { + setMessage({ + type: 'error', + text: data.error || 'Upload failed', + }); + } + } catch (error: any) { + setMessage({ + type: 'error', + text: error.message || 'Upload failed', + }); + } finally { + setIsUploading(false); + // Reset file input + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + } + }; + + return ( +
+

Upload CSV Data

+ + + + + + {message && ( +
+ {message.text} +
+ )} +
+ ); +} diff --git a/src/components/Toolbox.tsx b/src/components/Toolbox.tsx new file mode 100644 index 0000000..1ae0cbc --- /dev/null +++ b/src/components/Toolbox.tsx @@ -0,0 +1,79 @@ +'use client'; + +import { useState } from 'react'; +import { ArrowUpCircle, ArrowDownCircle, TrendingUp, Trash2, Download } from 'lucide-react'; +import { Button } from '@/components/ui/button'; + +export type Tool = 'break_up' | 'break_down' | 'line' | 'delete' | null; + +interface ToolboxProps { + activeTool: Tool; + onToolChange: (tool: Tool) => void; + onExport: () => void; +} + +export default function Toolbox({ activeTool, onToolChange, onExport }: ToolboxProps) { + const handleToolClick = (tool: Tool) => { + // Toggle: if clicking the active tool, deactivate it + if (activeTool === tool) { + onToolChange(null); + } else { + onToolChange(tool); + } + }; + + return ( +
+

Annotation Tools

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