feat: create detailed implementation tasks (107 checkboxed tasks)
Breakdown into 16 phases: 1. Setup and Configuration (3 tasks) 2. API Extensions for Bulk Operations (8 tasks) 3. Hacker Theme - CSS Variables and Tailwind (12 tasks) 4. Hacker Theme - Component Styling (6 tasks) 5. Label Management - State and Selection (9 tasks) 6. Label Management - Keyboard Delete (7 tasks) 7. Label Management - Sidebar List UI Structure (8 tasks) 8. Label Management - Sidebar List Content (11 tasks) 9. Label Management - Search and Filter (8 tasks) 10. Label Management - Delete All Labels Button (9 tasks) 11. Toast Feedback System (8 tasks) 12. Docker - Dockerfile Creation (14 tasks) 13. Docker - Compose Configuration (12 tasks) 14. Documentation Updates (10 tasks) 15. Integration Testing and Validation (15 tasks) 16. Commit and Cleanup (8 tasks) Each task is small, specific, and verifiable. Perfect for Haiku model execution.
This commit is contained in:
parent
ce96895bc3
commit
74b84073a9
1 changed files with 197 additions and 0 deletions
|
|
@ -0,0 +1,197 @@
|
|||
# Implementation Tasks
|
||||
|
||||
## 1. Setup and Configuration
|
||||
|
||||
- [ ] 1.1 Load JetBrains Mono font from Google Fonts in `src/app/layout.tsx` (add to head with weights 400, 500, 700)
|
||||
- [ ] 1.2 Update `next.config.js` to enable standalone output mode (`output: 'standalone'`)
|
||||
- [ ] 1.3 Verify all existing features work (run dev server, test line drawing, label placement, delete tool)
|
||||
|
||||
## 2. API Extensions for Bulk Operations
|
||||
|
||||
- [ ] 2.1 Read existing `src/app/api/annotations/route.ts` DELETE handler
|
||||
- [ ] 2.2 Add query parameter parsing in DELETE handler (`type` and `all` params from `request.nextUrl.searchParams`)
|
||||
- [ ] 2.3 Add conditional WHERE clause logic: if `type` param exists, filter by `label_type IN (comma-separated types)`, if `all=true` delete everything, else return 400 error
|
||||
- [ ] 2.4 Update return value to include count: `{ success: true, deleted: <count> }` using `result.length` from Drizzle delete operation
|
||||
- [ ] 2.5 Test bulk delete via curl: `curl -X DELETE "http://localhost:3000/api/annotations?type=break_up"` (verify count returned)
|
||||
- [ ] 2.6 Create new file `src/app/api/health/route.ts` with GET handler returning `{ status: 'ok', timestamp: Date.now() }`
|
||||
- [ ] 2.7 Add optional database check in health endpoint: if `?check=db` query param exists, attempt simple `SELECT 1` query and return 503 on failure
|
||||
- [ ] 2.8 Test health endpoint: `curl http://localhost:3000/api/health` (verify 200 response)
|
||||
|
||||
## 3. Hacker Theme - CSS Variables and Tailwind
|
||||
|
||||
- [ ] 3.1 Read current `src/app/globals.css` and note existing CSS variable names
|
||||
- [ ] 3.2 Replace CSS variable values in `:root` with hacker theme colors: `--background: 120 100% 4%` (#0a0e0a), `--foreground: 120 100% 50%` (#00ff41), `--primary: 120 100% 50%`, `--destructive: 348 100% 50%` (#ff0040), `--border: 120 100% 10%` (#003311), map all other variables to theme equivalents
|
||||
- [ ] 3.3 Update body font-family in `globals.css` to: `font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;`
|
||||
- [ ] 3.4 Add custom selection styling in `globals.css`: `::selection { background: rgba(0, 255, 65, 0.4); color: #00ff41; }`
|
||||
- [ ] 3.5 Add custom scrollbar styles in `globals.css`: `::-webkit-scrollbar { width: 8px; }`, `::-webkit-scrollbar-track { background: #003311; }`, `::-webkit-scrollbar-thumb { background: #00ff41; border-radius: 4px; }`
|
||||
- [ ] 3.6 Read `tailwind.config.ts` and locate `theme.extend.colors` object
|
||||
- [ ] 3.7 Add custom colors to Tailwind config: `matrix: '#00ff41'`, `matrixDim: '#00cc33'`, `matrixDark: '#003311'`, `neonRed: '#ff0040'`, `neonCyan: '#00d4ff'`, `neonYellow: '#ffff00'`, `terminal: '#0a0e0a'`, `terminalLight: '#0d110d'`
|
||||
- [ ] 3.8 Add custom fontFamily to Tailwind config: `mono: ['JetBrains Mono', 'Fira Code', 'Courier New', 'monospace']`
|
||||
- [ ] 3.9 Add custom boxShadow to Tailwind config: `'glow-sm': '0 0 8px #00ff41'`, `'glow': '0 0 15px #00ff41, 0 0 30px rgba(0,255,65,0.5)'`, `'glow-lg': '0 0 20px #00ff41, 0 0 40px rgba(0,255,65,0.5)'`
|
||||
- [ ] 3.10 Add keyframes to Tailwind config: `'glow-pulse': { '0%, 100%': { boxShadow: '0 0 15px #00ff41' }, '50%': { boxShadow: '0 0 30px #00ff41, 0 0 50px rgba(0,255,65,0.5)' } }`, `'flicker': { '0%, 100%': { opacity: '1' }, '50%': { opacity: '0.8' } }`
|
||||
- [ ] 3.11 Add animations to Tailwind config: `'glow-pulse': 'glow-pulse 2s ease-in-out infinite'`, `'flicker': 'flicker 0.1s ease-in-out'`
|
||||
- [ ] 3.12 Test theme in browser: verify green text, black background, monospace font on all elements
|
||||
|
||||
## 4. Hacker Theme - Component Styling
|
||||
|
||||
- [ ] 4.1 Read `src/components/Toolbox.tsx` and identify button elements
|
||||
- [ ] 4.2 Update button hover states in Toolbox to add glow effect: add `hover:shadow-glow` class to all Button components
|
||||
- [ ] 4.3 Update active tool buttons in Toolbox: when `activeTool` matches, add `animate-glow-pulse` class
|
||||
- [ ] 4.4 Update input field styling (search input in label list, if exists): add `focus:shadow-glow-sm focus:border-matrix` classes
|
||||
- [ ] 4.5 Read `src/components/ui/button.tsx` and add destructive variant glow: in destructive variant, change hover shadow to red: `hover:shadow-[0_0_15px_#ff0040]`
|
||||
- [ ] 4.6 Test button styling: hover over buttons (should glow green), click to activate tool (should pulse), hover delete button (should glow red)
|
||||
|
||||
## 5. Label Management - State and Selection
|
||||
|
||||
- [ ] 5.1 Read `src/app/page.tsx` and locate existing state declarations (activeTool, selectedColor, etc.)
|
||||
- [ ] 5.2 Add new state in page.tsx: `const [selectedLabelId, setSelectedLabelId] = useState<number | null>(null)`
|
||||
- [ ] 5.3 Pass selectedLabelId and setSelectedLabelId as props to CandleChart component
|
||||
- [ ] 5.4 Read `src/components/CandleChart.tsx` and locate marker creation code (where break_up/break_down markers are added)
|
||||
- [ ] 5.5 Add onClick handler to marker options: in marker creation config, add `onClick: () => props.onLabelSelect?.(annotation.id)`
|
||||
- [ ] 5.6 Update CandleChart props interface to accept `selectedLabelId: number | null`, `onLabelSelect: (id: number) => void`
|
||||
- [ ] 5.7 Wire up onLabelSelect in page.tsx: `onLabelSelect={(id) => setSelectedLabelId(id === selectedLabelId ? null : id)}`
|
||||
- [ ] 5.8 Add visual highlight for selected marker: when rendering markers, if `annotation.id === selectedLabelId`, set marker size to 1.5x and add glow effect (modify marker shape/color options)
|
||||
- [ ] 5.9 Test label selection: click on break_up arrow (should highlight), click again (should deselect), click different marker (should switch selection)
|
||||
|
||||
## 6. Label Management - Keyboard Delete
|
||||
|
||||
- [ ] 6.1 Read `src/app/page.tsx` and locate any existing keyboard event handlers
|
||||
- [ ] 6.2 Add global keyboard handler in page.tsx useEffect: `window.addEventListener('keydown', handleKeyDown)`
|
||||
- [ ] 6.3 Implement handleKeyDown function: if `e.key === 'Delete' || e.key === 'Backspace'`, check if `selectedLabelId !== null`
|
||||
- [ ] 6.4 In handleKeyDown, when Delete pressed with selected label: call `fetch('/api/annotations/' + selectedLabelId, { method: 'DELETE' })`
|
||||
- [ ] 6.5 After successful delete, call chart refresh method and reset `setSelectedLabelId(null)`
|
||||
- [ ] 6.6 Add cleanup in useEffect: `return () => window.removeEventListener('keydown', handleKeyDown)`
|
||||
- [ ] 6.7 Test keyboard delete: select a label marker, press Delete key (marker should disappear), verify database updated
|
||||
|
||||
## 7. Label Management - Sidebar List UI Structure
|
||||
|
||||
- [ ] 7.1 Read `src/components/Toolbox.tsx` and locate the export button section (bottom of component)
|
||||
- [ ] 7.2 Import Collapsible components from shadcn/ui: check if `src/components/ui/collapsible.tsx` exists, if not install via `npx shadcn@latest add collapsible`
|
||||
- [ ] 7.3 Add state in Toolbox for collapsed state: `const [labelsExpanded, setLabelsExpanded] = useState(true)`
|
||||
- [ ] 7.4 Add new section above Export button: wrap in Collapsible component with `open={labelsExpanded}` and `onOpenChange={setLabelsExpanded}`
|
||||
- [ ] 7.5 Create section header button: "Label Annotations (X)" with ChevronDown/ChevronUp icon from lucide-react, clicking toggles `labelsExpanded`
|
||||
- [ ] 7.6 Inside Collapsible.Content, add container div with `className="max-h-96 overflow-y-auto space-y-2 p-2"`
|
||||
- [ ] 7.7 Add count display in header: calculate `breakUpCount` and `breakDownCount` from props.annotations filtered by `label_type`, display as "Break Up: X | Break Down: Y"
|
||||
- [ ] 7.8 Test collapsible: click header (should expand/collapse), verify smooth animation
|
||||
|
||||
## 8. Label Management - Sidebar List Content
|
||||
|
||||
- [ ] 8.1 Update Toolbox props to accept `annotations: Annotation[]`, `selectedLabelId: number | null`, `onLabelSelect: (id: number) => void`, `onLabelDelete: (id: number) => void`
|
||||
- [ ] 8.2 Pass annotations from page.tsx to Toolbox (retrieve from CandleChart or fetch directly in page.tsx)
|
||||
- [ ] 8.3 Filter annotations in Toolbox: `const labelAnnotations = annotations.filter(a => a.label_type === 'break_up' || a.label_type === 'break_down')`
|
||||
- [ ] 8.4 Sort labelAnnotations by timestamp descending: `labelAnnotations.sort((a, b) => b.timestamp - a.timestamp)`
|
||||
- [ ] 8.5 Map over labelAnnotations to render list items: each item in a div with border, padding, cursor-pointer, onClick calls onLabelSelect
|
||||
- [ ] 8.6 Format timestamp in each item: `new Date(timestamp * 1000).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })`
|
||||
- [ ] 8.7 Add colored badge for label type: break_up shows "BREAK UP" in green bg, break_down shows "BREAK DOWN" in red bg
|
||||
- [ ] 8.8 Add delete button (trash icon) to each item: onClick calls `onLabelDelete(annotation.id)` with stopPropagation to prevent selection
|
||||
- [ ] 8.9 Highlight selected item: if `annotation.id === selectedLabelId`, add border-matrix and bg-matrix/10 classes
|
||||
- [ ] 8.10 Handle empty state: if labelAnnotations.length === 0, show message "No labels yet. Click Break Up or Break Down tools to add labels."
|
||||
- [ ] 8.11 Test list rendering: add several labels, verify they appear sorted by time, click to select, click delete button (should remove)
|
||||
|
||||
## 9. Label Management - Search and Filter
|
||||
|
||||
- [ ] 9.1 Add state for search in Toolbox: `const [searchText, setSearchText] = useState('')`
|
||||
- [ ] 9.2 Add state for filter in Toolbox: `const [filterType, setFilterType] = useState<'all' | 'break_up' | 'break_down'>('all')`
|
||||
- [ ] 9.3 Add search input above label list: Input component with placeholder "Search by timestamp...", value={searchText}, onChange={e => setSearchText(e.target.value)}
|
||||
- [ ] 9.4 Add filter dropdown above label list: Select or dropdown with options "All", "Break Up", "Break Down", value={filterType}, onChange={setFilterType}
|
||||
- [ ] 9.5 Apply filter to labelAnnotations: if filterType !== 'all', filter array by `a.label_type === filterType`
|
||||
- [ ] 9.6 Apply search to labelAnnotations: filter by formatted timestamp includes searchText (case-insensitive): `formattedTimestamp.toLowerCase().includes(searchText.toLowerCase())`
|
||||
- [ ] 9.7 Update count display to show filtered count: "Showing X of Y labels"
|
||||
- [ ] 9.8 Test search: type "Feb" in search (should filter to February dates), test filter: select "Break Up" (should show only break_up labels)
|
||||
|
||||
## 10. Label Management - Delete All Labels Button
|
||||
|
||||
- [ ] 10.1 Import Dialog components from shadcn/ui: check if `src/components/ui/dialog.tsx` exists, if not install via `npx shadcn@latest add dialog`
|
||||
- [ ] 10.2 Add state for confirmation dialog: `const [deleteAllDialogOpen, setDeleteAllDialogOpen] = useState(false)`
|
||||
- [ ] 10.3 Add "Delete All Labels" button below search/filter controls: Button with destructive variant, onClick opens dialog, disabled if labelAnnotations.length === 0
|
||||
- [ ] 10.4 Create Dialog component with AlertDialog pattern: AlertDialogTitle "Delete all label annotations?", AlertDialogDescription "This will remove all Break Up and Break Down markers. This cannot be undone."
|
||||
- [ ] 10.5 Add Cancel button in dialog: onClick closes dialog without action
|
||||
- [ ] 10.6 Add Confirm button in dialog: destructive variant, onClick calls API DELETE with type=break_up,break_down
|
||||
- [ ] 10.7 Implement delete all handler: `fetch('/api/annotations?type=break_up,break_down', { method: 'DELETE' })`, on success refresh annotations and close dialog
|
||||
- [ ] 10.8 Show toast notification after delete: use shadcn toast to display "> SUCCESS: Deleted all labels [X items]"
|
||||
- [ ] 10.9 Test delete all: add multiple labels, click Delete All Labels, confirm dialog (all should disappear), verify database emptied
|
||||
|
||||
## 11. Toast Feedback System
|
||||
|
||||
- [ ] 11.1 Install shadcn toast if not present: `npx shadcn@latest add toast`
|
||||
- [ ] 11.2 Read `src/components/ui/toast.tsx` and `src/hooks/use-toast.ts`
|
||||
- [ ] 11.3 Update toast styling in `toast.tsx`: add `font-mono` class, update border color to use matrix theme colors
|
||||
- [ ] 11.4 Import and add Toaster component in `src/app/layout.tsx` (add `<Toaster />` in body)
|
||||
- [ ] 11.5 Create useToast hook wrapper in components that need feedback: import `{ useToast } from '@/hooks/use-toast'`
|
||||
- [ ] 11.6 Add toast calls after successful operations: delete label → `toast({ title: "> SUCCESS", description: "Deleted label [1 item]" })`
|
||||
- [ ] 11.7 Add toast calls for errors: catch API errors → `toast({ title: "> ERROR", description: "Failed to delete [code: 500]", variant: "destructive" })`
|
||||
- [ ] 11.8 Test toast: perform delete operation (should see green success toast), cause error by disconnecting network (should see red error toast)
|
||||
|
||||
## 12. Docker - Dockerfile Creation
|
||||
|
||||
- [ ] 12.1 Create `.dockerignore` file in project root with contents: `node_modules`, `.next`, `.git`, `data/`, `*.md`, `.env*`, `*.log`, `coverage/`, `.DS_Store`
|
||||
- [ ] 12.2 Create `Dockerfile` in project root: start with `FROM node:18-alpine AS builder`
|
||||
- [ ] 12.3 Add build stage instructions: `WORKDIR /app`, `COPY package*.json ./`, `RUN npm ci`, `COPY . .`, `RUN npm run build`
|
||||
- [ ] 12.4 Add production stage: `FROM node:18-alpine`, `WORKDIR /app`
|
||||
- [ ] 12.5 Create non-root user: `RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001`
|
||||
- [ ] 12.6 Copy standalone files: `COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./`
|
||||
- [ ] 12.7 Copy static files: `COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static`
|
||||
- [ ] 12.8 Copy public files: `COPY --from=builder --chown=nextjs:nodejs /app/public ./public`
|
||||
- [ ] 12.9 Create data directory: `RUN mkdir -p /app/data && chown nextjs:nodejs /app/data`
|
||||
- [ ] 12.10 Set environment variables: `ENV NODE_ENV=production PORT=3000 HOSTNAME=0.0.0.0`
|
||||
- [ ] 12.11 Set user and expose port: `USER nextjs`, `EXPOSE 3000`
|
||||
- [ ] 12.12 Add healthcheck: `HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1`
|
||||
- [ ] 12.13 Set CMD: `CMD ["node", "server.js"]`
|
||||
- [ ] 12.14 Test Dockerfile: run `docker build -t candle-annotator .` (should build successfully, check image size with `docker images`)
|
||||
|
||||
## 13. Docker - Compose Configuration
|
||||
|
||||
- [ ] 13.1 Create `docker-compose.yml` in project root
|
||||
- [ ] 13.2 Set compose version: `version: '3.8'` (or use no version for latest)
|
||||
- [ ] 13.3 Define service: `services: candle-annotator:`
|
||||
- [ ] 13.4 Add build context: `build: .`
|
||||
- [ ] 13.5 Add port mapping: `ports: - "3000:3000"`
|
||||
- [ ] 13.6 Add volume mount: `volumes: - candle-data:/app/data`
|
||||
- [ ] 13.7 Add environment variables: `environment: - NODE_ENV=production` (optionally use `env_file: .env`)
|
||||
- [ ] 13.8 Add restart policy: `restart: unless-stopped`
|
||||
- [ ] 13.9 Define named volume: `volumes: candle-data:`
|
||||
- [ ] 13.10 Create `.env.example` file with template variables: `NODE_ENV=production`, `PORT=3000`, `DATABASE_PATH=/app/data/candles.db`
|
||||
- [ ] 13.11 Test compose: run `docker-compose up --build` (should start container and be accessible at http://localhost:3000)
|
||||
- [ ] 13.12 Test persistence: upload CSV, add annotations, stop container (`docker-compose down`), restart (`docker-compose up`), verify data persists
|
||||
|
||||
## 14. Documentation Updates
|
||||
|
||||
- [ ] 14.1 Read existing `DEPLOYMENT.md` file
|
||||
- [ ] 14.2 Add "Docker Deployment" section with prerequisites (Docker, docker-compose installed)
|
||||
- [ ] 14.3 Add build instructions: `docker-compose build` or `docker build -t candle-annotator .`
|
||||
- [ ] 14.4 Add run instructions: `docker-compose up -d` for detached mode, `docker-compose logs -f` to view logs
|
||||
- [ ] 14.5 Add environment setup: copy `.env.example` to `.env`, edit variables as needed
|
||||
- [ ] 14.6 Add volume management: explain data persists in `candle-data` volume, show backup command `docker cp candle-annotator:/app/data/candles.db ./backup.db`
|
||||
- [ ] 14.7 Add troubleshooting section: port conflicts (change PORT in .env), permission errors (check volume ownership), build failures (clear cache with `docker-compose build --no-cache`)
|
||||
- [ ] 14.8 Add update procedure: `git pull`, `docker-compose down`, `docker-compose up --build -d`
|
||||
- [ ] 14.9 Update `README.md` with Docker quickstart: add section "Docker Deployment" linking to DEPLOYMENT.md
|
||||
- [ ] 14.10 Update `CLAUDE_DESCRIPTION.md` with new features: label management sidebar, hacker theme, Docker support
|
||||
|
||||
## 15. Integration Testing and Validation
|
||||
|
||||
- [ ] 15.1 Test full label workflow: create 10 break_up and 10 break_down labels using chart tools
|
||||
- [ ] 15.2 Test label selection: click markers on chart (should highlight), verify selection state reflected in sidebar list
|
||||
- [ ] 15.3 Test sidebar list: verify all 20 labels appear sorted by timestamp, click list item (should highlight marker on chart)
|
||||
- [ ] 15.4 Test search: type partial timestamp (should filter list), clear search (should show all)
|
||||
- [ ] 15.5 Test filter: select "Break Up" filter (should show only 10 items), select "Break Down" (should show other 10), select "All" (should show 20)
|
||||
- [ ] 15.6 Test delete individual label: click trash icon on list item (should remove from list and chart), verify database updated
|
||||
- [ ] 15.7 Test delete all labels: click "Delete All Labels" button, confirm dialog (all 20 should disappear), verify success toast appears
|
||||
- [ ] 15.8 Test keyboard delete: create label, click to select, press Delete key (should remove), create another, press Backspace (should remove)
|
||||
- [ ] 15.9 Test existing line features: draw lines (should still work), select lines (should still work), drag endpoints (should still work), delete lines (should still work)
|
||||
- [ ] 15.10 Test theme visual appearance: verify monospace font on all text, green color scheme throughout, glow effects on hover, borders and shadows match specs
|
||||
- [ ] 15.11 Test health endpoint: `curl http://localhost:3000/api/health` (should return 200 with { status: 'ok' }), test with db check `curl http://localhost:3000/api/health?check=db`
|
||||
- [ ] 15.12 Test Docker deployment: build image, start container, access http://localhost:3000, upload CSV, create annotations, verify persistence after restart
|
||||
- [ ] 15.13 Test contrast and accessibility: use browser dev tools to check contrast ratios (should meet WCAG AA 4.5:1), test with prefers-reduced-motion (animations should disable)
|
||||
- [ ] 15.14 Verify no breaking changes: compare current functionality with pre-change state, confirm all original features work identically
|
||||
- [ ] 15.15 Final smoke test: clean database, fresh Docker build, complete annotation workflow from CSV upload to export, verify output CSV includes all annotations
|
||||
|
||||
## 16. Commit and Cleanup
|
||||
|
||||
- [ ] 16.1 Review all changed files with `git status` and `git diff`
|
||||
- [ ] 16.2 Commit label management changes: `git add src/app/page.tsx src/components/CandleChart.tsx src/components/Toolbox.tsx` and commit with message "feat: implement label management with sidebar list and search"
|
||||
- [ ] 16.3 Commit API changes: `git add src/app/api/` and commit with message "feat: add bulk delete API and health endpoint"
|
||||
- [ ] 16.4 Commit theme changes: `git add src/app/globals.css tailwind.config.ts src/app/layout.tsx src/components/ui/` and commit with message "feat: implement hacker theme with matrix colors and monospace fonts"
|
||||
- [ ] 16.5 Commit Docker files: `git add Dockerfile docker-compose.yml .dockerignore .env.example next.config.js` and commit with message "feat: add Docker deployment with multi-stage build"
|
||||
- [ ] 16.6 Commit documentation: `git add README.md DEPLOYMENT.md CLAUDE_DESCRIPTION.md` and commit with message "docs: update deployment and feature documentation"
|
||||
- [ ] 16.7 Tag release: `git tag v2.0.0 -m "Release: Label management, Docker deployment, hacker theme"`
|
||||
- [ ] 16.8 Push to remote: `git push origin master --tags`
|
||||
Loading…
Add table
Add a link
Reference in a new issue