diff --git a/CLAUDE.md b/CLAUDE.md index 489fa6e..735556d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,1116 +1,89 @@ # CLAUDE.md - AI Assistant Codebase Guide **Last Updated:** 2026-03-09 -**Version:** 1.0.6 +**Version:** 2.0.0 -This document provides comprehensive guidance for AI assistants working with the TimeTracker Pro codebase. It covers architecture, conventions, workflows, and best practices. - ---- - -## Table of Contents - -1. [Project Overview](#project-overview) -2. [Technology Stack](#technology-stack) -3. [Architecture Patterns](#architecture-patterns) -4. [File Organization](#file-organization) -5. [Data Flow & State Management](#data-flow--state-management) -6. [Key Conventions](#key-conventions) -7. [Development Workflow](#development-workflow) -8. [Common Operations](#common-operations) -9. [Testing & Quality](#testing--quality) -10. [Pitfalls & Gotchas](#pitfalls--gotchas) -11. [AI-Specific Guidance](#ai-specific-guidance) - ---- - -## Project Overview - -### What is TimeTracker Pro? - -TimeTracker Pro is a modern time tracking application built for freelancers, consultants, and professionals. It enables users to: - -- Track work hours by task, project, and client -- Manage billable and non-billable time -- Generate invoices and export data -- Sync data across devices (optional cloud sync) -- Work offline with local storage - -### Key Features - -- **Dual Storage Mode**: Works with or without authentication - - **Guest Mode**: localStorage only, no account needed - - **Authenticated Mode**: Supabase cloud sync across devices -- **Time Tracking**: Start/stop day, create tasks, automatic duration calculation -- **Project Management**: Hourly rates, client assignments, billable/non-billable flags -- **Category System**: Organize tasks with custom categories -- **Archive System**: Permanent record of completed work days -- **Export/Import**: CSV and JSON formats, database-compatible schema -- **Revenue Tracking**: Automatic calculation based on hourly rates -- **Weekly Report**: AI-generated work summaries (standup, client, retrospective tones) sourced from `archivedDays` via context — works in both guest and authenticated modes -- **Responsive Design**: Works on desktop and mobile - -### Project Origin - -Originally created via Lovable.dev prompts, now actively maintained. See `info/README-LOVABLE.md` for history. +TimeTracker Pro is a React 18 + TypeScript time tracking PWA for freelancers and consultants, with dual storage (localStorage guest mode and optional Supabase cloud sync). --- ## Technology Stack -### Core Technologies - -- **React 18** - UI framework with TypeScript -- **TypeScript 5.8** - Type safety and developer experience -- **Vite 5** - Build tool and dev server -- **React Router 6** - Client-side routing - -### UI & Styling - -- **Tailwind CSS 3** - Utility-first CSS framework -- **Radix UI** - Accessible, unstyled component primitives -- **shadcn/ui** - Pre-built component library built on Radix -- **Lucide React** - Icon library (primary) -- **Radix Icons** - Icon library (fallback) -- **next-themes** - Dark mode support - -### Data & Backend - -- **Supabase** - Backend as a Service (optional) - - PostgreSQL database - - Authentication (email/password) - - Real-time capabilities (currently disabled for single-device usage) -- **localStorage** - Browser storage for offline/guest mode - -### State Management - -- **React Context API** - Global state management -- **Custom Hooks** - Reusable stateful logic - - `useAuth` - Authentication state - - `useTimeTracking` - Time tracking operations - - `useRealtimeSync` - Database sync (currently disabled) - -### Forms & Validation - -- **React Hook Form** - Form state management -- **Zod** - Schema validation -- **@hookform/resolvers** - Form resolver integration - -### Progressive Web App (PWA) - -- **Vite PWA Plugin** - Service worker and manifest generation -- **Workbox** - Service worker caching strategies -- **Service Worker** - Offline support and caching -- **Web App Manifest** - App metadata and icons - -### Build & Development - -- **Vite + SWC** - Fast builds and hot module replacement -- **ESLint 9** - Code quality and style checking -- **Vitest** - Unit testing framework -- **@testing-library/react** - Component testing utilities -- **Playwright** - Automated screenshot generation and E2E testing - ---- - -## Architecture Patterns - -### Overall Architecture - -TimeTracker Pro follows a **context-driven architecture** with **service-oriented data layer**: - -``` -┌─────────────────────────────────────────────────────────┐ -│ App.tsx │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ AuthProvider (Context) │ │ -│ │ ┌──────────────────────────────────────────────┐ │ │ -│ │ │ TimeTrackingProvider (Context) │ │ │ -│ │ │ │ │ │ -│ │ │ ┌────────────────────────────────────────┐ │ │ │ -│ │ │ │ Pages & Components │ │ │ │ -│ │ │ └────────────────────────────────────────┘ │ │ │ -│ │ └──────────────────────────────────────────────┘ │ │ -│ └────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────┘ - │ - ▼ - ┌───────────────────────┐ - │ DataService Layer │ - │ (Factory Pattern) │ - └───────────────────────┘ - │ │ - ┌───────────┘ └───────────┐ - ▼ ▼ -┌──────────────────┐ ┌──────────────────┐ -│ LocalStorage │ │ Supabase │ -│ Service │ │ Service │ -└──────────────────┘ └──────────────────┘ -``` - -### Key Patterns - -#### 1. Context Provider Pattern - -All global state is managed through React Context: -- `AuthContext` - User authentication and session -- `TimeTrackingContext` - All time tracking operations - -#### 2. Service Layer Pattern - -Data persistence is abstracted through the `DataService` interface: -- **Interface**: `DataService` defines all data operations -- **Implementations**: - - `LocalStorageService` - For guest/offline mode - - `SupabaseService` - For authenticated/cloud mode -- **Factory**: `createDataService(isAuthenticated)` returns appropriate implementation - -#### 3. Custom Hook Pattern - -Complex logic is extracted into custom hooks: -- `useAuth()` - Access authentication state and methods -- `useTimeTracking()` - Access time tracking state and methods -- `useRealtimeSync()` - Real-time sync (currently disabled) - -#### 4. Lazy Loading Pattern - -Pages are lazy-loaded for code splitting: -```typescript -const Index = lazy(() => import('./pages/Index')); -``` - -#### 5. Optimistic UI Updates - -UI updates immediately, then syncs to backend: -```typescript -setTasks(prev => [...prev, newTask]); // Update UI -await dataService.saveCurrentDay(state); // Sync to backend -``` - ---- - -## File Organization - -### Directory Structure - -``` -TimeTrackerPro/ -├── src/ -│ ├── components/ # React components -│ │ ├── ui/ # shadcn/ui base components (49 files) -│ │ │ └── scroll-time-picker.tsx # Custom scroll-wheel time picker -│ │ ├── ArchiveEditDialog.tsx # Archive entry editing -│ │ ├── ArchiveItem.tsx # Archive display component -│ │ ├── AuthDialog.tsx # Authentication modal -│ │ ├── CategoryManagement.tsx # Category management UI -│ │ ├── DaySummary.tsx # Day summary display -│ │ ├── DeleteConfirmationDialog.tsx # Deletion confirmations -│ │ ├── ExportDialog.tsx # Export functionality UI -│ │ ├── InstallPrompt.tsx # PWA install prompt -│ │ ├── MobileNav.tsx # Mobile bottom navigation (PWA) -│ │ ├── Navigation.tsx # App navigation -│ │ ├── NewTaskForm.tsx # Task creation form -│ │ ├── ProjectManagement.tsx # Project management UI -│ │ ├── SyncStatus.tsx # Sync status indicator -│ │ ├── TaskEditDialog.tsx # Task editing dialog -│ │ ├── TaskItem.tsx # Task display component -│ │ ├── UpdateNotification.tsx # PWA update notification -│ │ └── UserMenu.tsx # User menu dropdown -│ ├── config/ # Configuration files -│ │ ├── categories.ts # Default task categories -│ │ └── projects.ts # Default projects -│ ├── contexts/ # React Context providers -│ │ ├── AuthContext.tsx # Authentication -│ │ ├── OfflineContext.tsx # Offline queue (PWA) -│ │ └── TimeTrackingContext.tsx # Time tracking -│ ├── hooks/ # Custom React hooks -│ │ ├── useAuth.tsx # Auth hook -│ │ ├── useOffline.tsx # Offline state hook (PWA) -│ │ ├── useTimeTracking.tsx # Time tracking hook -│ │ ├── useReportSummary.ts # Gemini API call + error classification for /report -│ │ ├── use-toast.tsx # Toast notifications -│ │ └── useRealtimeSync.ts # Database sync -│ ├── lib/ # Utility libraries -│ │ ├── supabase.ts # Supabase client & helpers -│ │ └── util.ts # Utility functions -│ ├── pages/ # Page components -│ │ ├── Index.tsx # Home/time tracker -│ │ ├── Archive.tsx # Archived days -│ │ ├── ProjectList.tsx # Project management -│ │ ├── Categories.tsx # Category management -│ │ ├── Report.tsx # AI weekly summary generator -│ │ ├── Settings.tsx # App settings -│ │ └── NotFound.tsx # 404 page -│ ├── services/ # Business logic services -│ │ └── dataService.ts # Data persistence layer -│ ├── utils/ # Utility functions -│ │ ├── timeUtil.ts # Time formatting helpers -│ │ ├── reportUtils.ts # Report grouping, serialization, and DayRecord→ArchivedDay adapter -│ │ └── supabase.ts # Supabase utilities -│ ├── App.tsx # Root component -│ ├── main.tsx # Application entry point -│ └── vite-env.d.ts # Vite type definitions -├── public/ # Static assets -│ ├── icons/ # PWA app icons (8 sizes: 72-512px) -│ ├── screenshots/ # PWA screenshots (desktop + mobile) -│ ├── manifest.json # PWA web app manifest -│ ├── pwa.css # PWA-specific styles -│ └── ... # Other static assets -├── docs/ # Documentation -│ ├── ARCHIVING_DAYS.md # Archive system guide -│ ├── AUTHENTICATION.md # Auth setup and flow -│ ├── AUTH_DATA_PERSISTENCE_FIX.md # Auth data fix history -│ ├── CSV_TEMPLATES_README.md # CSV import/export templates -│ ├── FEATURES.md # Feature documentation -│ ├── MIGRATION.md # Data migration guide -│ ├── SCHEMA_COMPATIBILITY.md # Database schema history -│ ├── SECURITY.md # Security guidelines -│ └── chatbot.md # Chatbot integration info -├── agents/ # AI agent guidelines -│ ├── styles.md # Style rules -│ └── pull_requests.md # PR guidelines -├── tests/ # Test scripts -├── supabase/ # Supabase schema & migrations -├── .env.example # Environment template -├── package.json # Dependencies -├── tsconfig.json # TypeScript config -├── vite.config.ts # Vite configuration -├── tailwind.config.ts # Tailwind configuration -├── AGENTS.md # Agent instructions -├── README.md # Project documentation -└── CLAUDE.md # This file -``` - -### Key Files to Know - -| File | Purpose | -|------|---------| -| `src/contexts/TimeTrackingContext.tsx` | Main application state and logic (1400+ lines) | -| `src/services/dataService.ts` | Data persistence abstraction layer (1100+ lines) | -| `src/contexts/AuthContext.tsx` | Authentication state management | -| `src/lib/supabase.ts` | Supabase client configuration and caching | -| `src/config/categories.ts` | Default category definitions | -| `src/config/projects.ts` | Default project definitions | - ---- - -## Data Flow & State Management - -### Authentication Flow - -``` -1. User opens app - ↓ -2. AuthProvider checks for existing session - ↓ -3. If authenticated → Load from Supabase - If guest → Load from localStorage - ↓ -4. AuthContext provides: { user, isAuthenticated, loading, signIn, signUp, signOut } -``` - -### Time Tracking Flow - -``` -1. User starts day (via StartDayDialog) - ↓ -2. TimeTrackingContext updates state - ↓ -3. New Task form auto-opens (defaultOpen prop) - ↓ -4. User creates tasks - ↓ -5. Tasks saved to state (in-memory) - ↓ -6. Manual sync OR critical events (end day, window close) - ↓ -7. DataService persists to localStorage or Supabase -``` - -### Data Service Selection - -```typescript -// Factory pattern selects service based on auth state -const service = createDataService(isAuthenticated); -// Returns: LocalStorageService OR SupabaseService -``` - -### State Management Strategy - -**Current Design: Manual Sync (Single-Device Optimized)** - -- **No automatic saves** - Saves only on critical events -- **Critical save events**: - 1. Day end (`postDay()`) - 2. Window close (`beforeunload`) - 3. Manual sync button (`forceSyncToDatabase()`) -- **Why?** Optimized for single-device usage, reduces unnecessary database calls -- **Trade-off**: Users must manually sync or complete critical events - -### Data Migration - -**localStorage ↔ Supabase** - -- **Login**: Migrates localStorage data to Supabase (smart merge) -- **Logout**: Syncs Supabase data to localStorage for offline access -- **Logic**: Compares data freshness, prevents overwriting newer data +| Layer | Technology | +| ------------ | ------------------------------------------- | +| UI Framework | React 18 + TypeScript 5.8 | +| Build | Vite 5 + SWC | +| Routing | React Router 6 | +| Styling | Tailwind CSS 3 + Radix UI + shadcn/ui | +| Icons | Radix Icons (primary), Lucide (fallback) | +| Forms | React Hook Form + Zod | +| Backend | Supabase (optional) or localStorage | +| PWA | Vite PWA Plugin + Workbox | +| Testing | Vitest + React Testing Library + Playwright | --- -## Key Conventions - -### Code Style (CRITICAL) +## Critical Code Style — NON-NEGOTIABLE -⚠️ **These rules MUST be followed - they are project requirements** +⚠️ **These are hard project requirements enforced by the linter. Violating them causes build failures.** -#### Indentation & Quotes -- **Tabs, not spaces** - Always use tabs -- **Tab width**: 2 spaces -- **Quotes**: Always double quotes (`""`) never single quotes (`''`) +- **Indentation**: Tabs (not spaces), tab width = 2 +- **Quotes**: Always double quotes (`""`) — never single quotes (`''`) +- **Imports**: Always use `@/` alias — never relative paths like `../../` +- **Colors**: Always use Radix/theme variables — never custom Tailwind colors like `bg-blue-500` +- **Components**: Always use shadcn/ui components — never raw HTML with custom styles -#### Component Patterns ```typescript // ✅ CORRECT export const MyComponent = () => { - return ( -
-

Hello World

-
- ); + return
Hello
; }; -// ❌ WRONG - Uses spaces and single quotes +// ❌ WRONG — spaces, single quotes, custom color export const MyComponent = () => { - return ( -
-

Hello World

-
- ); -}; -``` - -#### File Naming -- **Components**: PascalCase (e.g., `TaskItem.tsx`, `NewTaskForm.tsx`) -- **Hooks**: camelCase with `use` prefix (e.g., `useAuth.tsx`) -- **Utilities**: camelCase (e.g., `timeUtil.ts`) -- **Config**: camelCase (e.g., `categories.ts`) - -#### Import Aliases -```typescript -// Use @ alias for src imports -import { Task } from "@/contexts/TimeTrackingContext"; -import { Button } from "@/components/ui/button"; - -// Not relative imports like ../../ -``` - -### UI & Styling Conventions - -#### Design System -- **Follow Radix UI guidelines**: [https://www.radix-ui.com](https://www.radix-ui.com) -- **Use Radix Colors**: [https://www.radix-ui.com/colors](https://www.radix-ui.com/colors) -- **Avoid custom colors** - Use theme variables instead - -#### Icons -1. **Primary**: Radix Icons - [https://www.radix-ui.com/icons](https://www.radix-ui.com/icons) -2. **Fallback**: Lucide - [https://lucide.dev](https://lucide.dev) - -#### Spacing & Typography -- **Follow Radix spacing**: [https://www.radix-ui.com/themes/docs/theme/spacing](https://www.radix-ui.com/themes/docs/theme/spacing) -- **Follow Radix typography**: [https://www.radix-ui.com/themes/docs/theme/typography](https://www.radix-ui.com/themes/docs/theme/typography) -- **Don't use custom spacing or font sizes** - Use theme values - -#### Component Usage -```typescript -// ✅ CORRECT - Using shadcn/ui components -import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent } from "@/components/ui/dialog"; - - - -// ❌ WRONG - Creating custom button styles - -``` - -### TypeScript Conventions - -#### Type Definitions -```typescript -// Main types in contexts -export interface Task { - id: string; - title: string; - description?: string; // Optional fields use ? - startTime: Date; - endTime?: Date; - duration?: number; - project?: string; - client?: string; - category?: string; -} - -// Use Partial<> for updates -updateTask: (taskId: string, updates: Partial) => void; -``` - -#### Loose Type Checking -- `noImplicitAny: false` - Allows implicit any -- `strictNullChecks: false` - Allows null/undefined without explicit checks -- Use types where helpful, but not strictly enforced - -### Naming Conventions - -#### Functions -- **Actions**: `startDay()`, `endDay()`, `startNewTask()` -- **Getters**: `getTotalDayDuration()`, `getCurrentTaskDuration()` -- **Setters**: `setIsDayStarted()`, `setTasks()` -- **Handlers**: `handleClick()`, `handleSubmit()` - -#### State Variables -- **Boolean**: `isDayStarted`, `isAuthenticated`, `loading`, `isSyncing` -- **Collections**: `tasks`, `projects`, `categories`, `archivedDays` -- **Single items**: `currentTask`, `user`, `dataService` - -#### Constants -- **UPPER_SNAKE_CASE**: `STORAGE_KEYS`, `DEFAULT_CATEGORIES` - ---- - -## Development Workflow - -### Initial Setup - -```bash -# Clone repository -git clone -cd TimeTrackerPro - -# Install dependencies -npm install - -# Setup environment (optional - for cloud sync) -cp .env.example .env -# Edit .env with your Supabase credentials - -# Start development server -npm run dev -# Opens on http://localhost:8080 -``` - -### Available Commands - -```bash -# Development -npm run dev # Start dev server (localhost:8080) -npm run build # Build for production -npm run build:dev # Build with development mode -npm run preview # Preview production build - -# Code Quality -npm run lint # Run ESLint -npm run test # Run Vitest tests - -# Testing Scripts -npm run test-full-import # Test full CSV import -npm run test-error-handling # Test CSV error handling -npm run test-csv-import # Test standard CSV import - -# PWA Screenshot Generation -npm run screenshots:install # Install Playwright browsers (first time only) -npm run screenshots # Capture PWA screenshots (headless) -npm run screenshots:headed # Capture screenshots with visible browser -``` - -**PWA Screenshot Usage:** -1. `npm run screenshots:install` - Install Playwright browsers (~300MB, one-time) -2. `npm run dev` - Start dev server (keep running) -3. `npm run screenshots` - Generate screenshots in new terminal -4. Screenshots saved to `public/screenshots/` - -See `tests/SCREENSHOTS_README.md` for detailed documentation. - -### Pre-Commit Checklist - -✅ **Before committing code:** -1. Run `npm run lint` - Fix all errors -2. Run `npm run build` - Ensure no type errors -3. Test functionality manually -4. Verify tabs (not spaces) and double quotes -5. Follow PR guidelines from `agents/pull_requests.md` - -### Git Workflow - -#### Branch Naming -- Feature branches: `claude/claude-md--` -- Always work on designated branch from session instructions - -#### Commit Messages -```bash -# Good commit messages -git commit -m "feat: add billable category option" -git commit -m "fix: data recovery issues" -git commit -m "refactor: improve data service caching" - -# Format: : -# Types: feat, fix, refactor, docs, style, test, chore -``` - -#### Creating Pull Requests -1. **Title Format**: `[TimeTrackerPro] ` -2. **Description**: Clear explanation of changes -3. **Wait for checks**: Don't merge until all tests pass -4. **Add labels**: Appropriate PR labels -5. **See**: `agents/pull_requests.md` for full guidelines - -### Working with Supabase - -#### Environment Setup -```bash -# .env file (never commit this!) -VITE_SUPABASE_URL=https://your-project.supabase.co -VITE_SUPABASE_ANON_KEY=your-anon-key -``` - -#### Database Schema Location -- Schema definitions: `supabase/migrations/` -- See `docs/SCHEMA_COMPATIBILITY.md` for schema history - ---- - -## Common Operations - -### Adding a New Feature Component - -```typescript -// 1. Create component file -// src/components/MyFeature.tsx - -import { useState } from "react"; -import { useTimeTracking } from "@/hooks/useTimeTracking"; -import { Button } from "@/components/ui/button"; - -export const MyFeature = () => { - const { tasks, addTask } = useTimeTracking(); - const [value, setValue] = useState(""); - - return ( -
- {/* Component content */} -
- ); -}; - -// 2. Import in page -// src/pages/Index.tsx -import { MyFeature } from "@/components/MyFeature"; -``` - -### Adding a New Page - -```typescript -// 1. Create page component -// src/pages/MyPage.tsx -import { Navigation } from "@/components/Navigation"; - -const MyPage = () => { - return ( -
- -
- {/* Page content */} -
-
- ); -}; - -export default MyPage; - -// 2. Add route in App.tsx -import { lazy } from "react"; -const MyPage = lazy(() => import("./pages/MyPage")); - -// In Routes: -} /> -``` - -### Using the TimePicker Component - -The `TimePicker` is a native HTML5 time input wrapped with shadcn/ui styling for consistent appearance and accessibility. - -**Component File**: `src/components/ui/scroll-time-picker.tsx` - -**Props Interface**: -```typescript -interface TimePickerProps { - value: string; // "HH:MM" 24-hour format (e.g., "14:30") - onValueChange: (value: string) => void; - disabled?: boolean; - className?: string; - id?: string; - "aria-label"?: string; - "aria-describedby"?: string; -} -``` - -**Usage Example**: -```typescript -import { TimePicker } from "@/components/ui/scroll-time-picker"; -import { Label } from "@/components/ui/label"; -import { useState } from "react"; - -const MyComponent = () => { - const [time, setTime] = useState("09:00"); - - return ( -
- - -
- ); -}; -``` - -**Features**: -- Native HTML5 `` for standard web UX -- **15-minute intervals**: Time selection restricted to :00, :15, :30, :45 using `step={900}` -- Mobile browsers display native time pickers automatically -- Desktop browsers provide keyboard-accessible spinners or typed input -- Full accessibility with ARIA labels, keyboard navigation, and screen reader support -- Styled with shadcn/ui design tokens (matches Input component) -- Supports dark mode via CSS variables -- Compatible with all modern browsers - -**Accessibility (A11y)**: -- Proper label association via `htmlFor` and `id` -- ARIA labels for screen readers -- Keyboard navigable (Tab, Arrow keys, Enter) -- Focus visible indicators -- Works with browser's native date/time accessibility features - -**Used In**: -- `StartDayDialog.tsx` - Day start time selection (1 picker) -- `TaskEditDialog.tsx` - Task start/end time selection (2 pickers) -- `ArchiveEditDialog.tsx` - Day and task time editing (4 pickers total) - -**Design Decision**: Native HTML5 inputs were chosen over custom implementations because: -1. Standard web pattern users already understand -2. Automatic mobile optimization (native pickers on iOS/Android) -3. Built-in accessibility features -4. Consistent with the app's date input approach -5. No custom scroll/wheel logic to maintain -6. Better keyboard navigation -7. Follows shadcn/ui philosophy of enhancing web standards - -**Migration Note**: This component replaced a custom scroll-wheel picker and earlier dropdown approach, providing better UX through browser-native functionality. - -### Adding a New Context Method - -```typescript -// 1. Define in interface (TimeTrackingContext.tsx) -interface TimeTrackingContextType { - // ... existing methods - myNewMethod: (param: string) => void; -} - -// 2. Implement in provider -const myNewMethod = (param: string) => { - // Implementation - console.log("Method called with:", param); -}; - -// 3. Export in value -return ( - - {children} - -); - -// 4. Use in components -const { myNewMethod } = useTimeTracking(); -myNewMethod("test"); -``` - -### Adding a Data Service Method - -```typescript -// 1. Add to interface (dataService.ts) -export interface DataService { - // ... existing methods - myDataOperation: (data: MyData) => Promise; -} - -// 2. Implement in LocalStorageService -class LocalStorageService implements DataService { - async myDataOperation(data: MyData): Promise { - localStorage.setItem("my_key", JSON.stringify(data)); - } -} - -// 3. Implement in SupabaseService -class SupabaseService implements DataService { - async myDataOperation(data: MyData): Promise { - const user = await getCachedUser(); - await supabase.from("my_table").insert(data); - } -} -``` - -### Modifying Database Schema - -```typescript -// 1. Update Supabase migration -// supabase/migrations/YYYYMMDD_description.sql - -ALTER TABLE tasks ADD COLUMN new_field TEXT; - -// 2. Update TypeScript types -// src/contexts/TimeTrackingContext.tsx - -export interface Task { - // ... existing fields - newField?: string; -} - -// 3. Update data service to handle new field -// src/services/dataService.ts - -const taskData = { - // ... existing fields - new_field: task.newField, + return
Hello
; }; ``` --- -## Testing & Quality - -### Running Tests - -```bash -# Unit tests -npm run test - -# Linting -npm run lint - -# Type checking -npm run build -``` - -### Manual Testing Checklist - -**Before submitting changes:** - -- [ ] Test in guest mode (no authentication) -- [ ] Test in authenticated mode -- [ ] Test on mobile viewport -- [ ] Test data persistence (refresh page) -- [ ] Test export/import functionality -- [ ] Verify no console errors -- [ ] Check responsive design - -**PWA-Specific Testing:** - -- [ ] Service worker registers successfully (DevTools → Application → Service Workers) -- [ ] App works offline (DevTools → Network → Offline) -- [ ] Install prompt appears (wait 30 seconds or test manually) -- [ ] App installs correctly on desktop (Chrome/Edge) -- [ ] Bottom navigation visible on mobile viewports -- [ ] Touch targets are large enough (44×44px minimum) -- [ ] Manifest loads without errors (DevTools → Application → Manifest) -- [ ] Update notification works when service worker updates - -### Code Quality Requirements - -1. **All lint errors must be fixed** before committing -2. **All TypeScript errors must be fixed** before merging -3. **Manual testing** of changed functionality required -4. **No breaking changes** without documentation - ---- - -## Pitfalls & Gotchas - -### Common Mistakes - -#### 1. Using Spaces Instead of Tabs -```typescript -// ❌ WRONG -export const Component = () => { - return
Content
; // Uses spaces -}; - -// ✅ CORRECT -export const Component = () => { - return
Content
; // Uses tabs -}; -``` - -#### 2. Using Single Quotes -```typescript -// ❌ WRONG -const message = 'Hello World'; - -// ✅ CORRECT -const message = "Hello World"; -``` - -#### 3. Not Using @ Alias -```typescript -// ❌ WRONG -import { Task } from "../../contexts/TimeTrackingContext"; - -// ✅ CORRECT -import { Task } from "@/contexts/TimeTrackingContext"; -``` - -#### 4. Creating Custom Colors -```typescript -// ❌ WRONG -
Content
- -// ✅ CORRECT -
Content
-``` - -#### 5. Forgetting to Save Data -```typescript -// ❌ WRONG - Data not persisted -setTasks([...tasks, newTask]); - -// ✅ CORRECT - Explicitly save -setTasks([...tasks, newTask]); -await forceSyncToDatabase(); // Or wait for critical event -``` - -#### 6. Bypassing the DataService (reading localStorage directly) -```typescript -// ❌ WRONG - Reads localStorage only; breaks for authenticated users whose -// data lives in Supabase, not localStorage -const raw = localStorage.getItem("timetracker_archived_days"); - -// ✅ CORRECT - Use the context, which routes through LocalStorageService -// or SupabaseService automatically -const { archivedDays } = useTimeTracking(); -``` - -Any utility that needs archived days must consume the context or accept -`DayRecord[]` as a parameter. Use `dayRecordsToArchivedDays()` from -`src/utils/reportUtils.ts` to convert to the `ArchivedDay[]` shape that -the report utils expect. - -### Architecture Gotchas - -#### 1. Manual Sync Required -- **Issue**: Data doesn't auto-save every change -- **Solution**: Use `forceSyncToDatabase()` or trigger critical events -- **Why**: Optimized for single-device usage - -#### 2. Category Lookup by ID -```typescript -// ❌ WRONG - Looking up by name -const category = categories.find(c => c.name === task.category); - -// ✅ CORRECT - Looking up by ID -const category = categories.find(c => c.id === task.category); -``` - -#### 3. Date Handling -```typescript -// ❌ WRONG - Date as string -const startTime = "2024-11-18"; - -// ✅ CORRECT - Date object -const startTime = new Date("2024-11-18"); -``` - -#### 4. Supabase User Caching -```typescript -// ❌ WRONG - Repeated auth calls (slow) -const { data: { user } } = await supabase.auth.getUser(); - -// ✅ CORRECT - Use cached user -const user = await getCachedUser(); -``` - -#### 5. Gemini API Error Classification - -Do **not** surface Gemini's raw `error.message` string to the user — it is often -vague ("high demand", "Resource has been exhausted") and gives no guidance on -whether to wait, fix a key, or switch plans. - -Always classify by HTTP status + `error.status` using `classifyGeminiError()` -in `src/hooks/useReportSummary.ts`. Key distinctions: - -| Symptom | HTTP | Gemini status | Meaning | -|---------|------|---------------|---------| -| Multiple consecutive failures | 503 | `UNAVAILABLE` | Server overloaded — retry in seconds | -| First request of the day fails | 429 | `RESOURCE_EXHAUSTED` + "quota" | Daily free-tier limit hit | -| Rapid retries fail | 429 | `RESOURCE_EXHAUSTED` + "rate" | Per-minute RPM limit — wait 30–60 s | -| Always fails | 403 | `PERMISSION_DENIED` | Bad API key | -| Always fails in region | 400 | `FAILED_PRECONDITION` | Free tier not available in region | +## Key Files -Also handle `finishReason` on 200 OK responses: a `SAFETY` or `RECITATION` -block returns HTTP 200 with an empty `text` — use `classifyFinishReason()`. - -### Performance Gotchas - -#### 1. Avoiding Unnecessary Re-renders -- Use `useCallback` for stable function references -- Use `useRef` for values that don't need re-renders -- Context updates trigger all consumers - -#### 2. Lazy Loading -- Pages are lazy-loaded - don't preload unnecessarily -- Use `` with fallback for lazy components +| File | Purpose | +| -------------------------------------- | ------------------------------------------------ | +| `src/contexts/TimeTrackingContext.tsx` | Main application state and logic (1400+ lines) | +| `src/services/dataService.ts` | Data persistence abstraction layer (1100+ lines) | +| `src/contexts/AuthContext.tsx` | Authentication state management | +| `src/lib/supabase.ts` | Supabase client configuration and caching | +| `src/config/categories.ts` | Default category definitions | +| `src/config/projects.ts` | Default project definitions | --- -## AI-Specific Guidance - -### When Working on This Codebase - -#### 1. Always Read First -Before making changes: -- Read the relevant context file (`TimeTrackingContext.tsx` or `AuthContext.tsx`) -- Read the data service implementation (`dataService.ts`) -- Check existing patterns in similar components - -#### 2. Follow Existing Patterns -- **Don't reinvent**: Use existing patterns for new features -- **Don't refactor**: Unless explicitly asked or fixing bugs -- **Don't optimize**: Unless there's a performance problem - -#### 3. Respect the Style Guide -- Tabs (2 spaces width), double quotes - NON-NEGOTIABLE -- Use Radix UI components and styling -- Follow existing naming conventions - -#### 4. Test Your Changes -Before claiming completion: -```bash -npm run lint # Must pass -npm run build # Must pass -# Manual testing required -``` - -#### 5. Understand Data Flow -``` -User Action - ↓ -Context Method - ↓ -State Update (in-memory) - ↓ -(Optional) DataService Call - ↓ -localStorage or Supabase -``` - -### Common AI Assistant Tasks - -#### Task: Add a new task property -1. Update `Task` interface in `TimeTrackingContext.tsx` -2. Update task creation in `startNewTask()` -3. Update database schema if using Supabase -4. Update `dataService.ts` to save/load new property -5. Update UI components to display/edit property -6. Test in both guest and authenticated modes - -#### Task: Add a new page -1. Create page component in `src/pages/` -2. Add route in `App.tsx` with lazy loading -3. Add navigation link in `Navigation.tsx` -4. Follow existing page layout patterns -5. Test routing and navigation - -#### Task: Fix a bug -1. **Reproduce**: Understand the bug completely -2. **Locate**: Find the relevant code -3. **Fix**: Make minimal changes to fix the issue -4. **Test**: Verify fix in all modes (guest + authenticated) -5. **Document**: Add comments if logic is complex - -#### Task: Add export/import functionality -1. Study existing `exportToCSV()` and `importFromCSV()` -2. Follow the exact CSV schema format -3. Handle errors gracefully -4. Validate data before import -5. Test with sample data files in `tests/` directory - -### Questions to Ask Yourself +## Pre-Commit Checklist -Before making changes, verify: - -- [ ] Does this follow the tab/double-quote convention? -- [ ] Am I using @ import aliases? -- [ ] Am I using existing UI components (not creating custom)? -- [ ] Have I checked how similar features are implemented? -- [ ] Will this work in both guest and authenticated modes? -- [ ] Do I need to update the data service for persistence? -- [ ] Have I tested the change manually? -- [ ] Will `npm run lint` and `npm run build` pass? +1. `npm run lint` — fix all errors +2. `npm run build` — ensure no type errors +3. Test changed functionality manually +4. Verify tabs (not spaces) and double quotes throughout --- -## Additional Resources - -### Documentation - -- **Main README**: `README.md` - User-facing documentation -- **Changelog**: `CHANGELOG.md` - Version history and changes -- **CLAUDE.md**: `CLAUDE.md` - This file - AI assistant guide -- **Agent Guidelines**: `AGENTS.md` - Quick agent instructions -- **Archive System**: `docs/ARCHIVING_DAYS.md` - Archive system guide -- **Authentication**: `docs/AUTHENTICATION.md` - Auth setup and flow -- **Auth Data Fix**: `docs/AUTH_DATA_PERSISTENCE_FIX.md` - Auth data fix history -- **CSV Templates**: `docs/CSV_TEMPLATES_README.md` - CSV import/export templates -- **Features**: `docs/FEATURES.md` - Feature documentation -- **Migration**: `docs/MIGRATION.md` - Data migration guide -- **Schema**: `docs/SCHEMA_COMPATIBILITY.md` - Database schema history -- **Security**: `docs/SECURITY.md` - Security guidelines -- **Chatbot**: `docs/chatbot.md` - Chatbot integration info -- **Agent Styles**: `agents/styles.md` - UI/UX guidelines -- **Pull Requests**: `agents/pull_requests.md` - PR guidelines - -### External References - -- **Radix UI**: [https://www.radix-ui.com](https://www.radix-ui.com) -- **shadcn/ui**: [https://ui.shadcn.com](https://ui.shadcn.com) -- **Tailwind CSS**: [https://tailwindcss.com](https://tailwindcss.com) -- **React Router**: [https://reactrouter.com](https://reactrouter.com) -- **Supabase Docs**: [https://supabase.com/docs](https://supabase.com/docs) -- **Vite**: [https://vitejs.dev](https://vitejs.dev) - -### Getting Help - -- **Issues**: Report bugs or request features via GitHub Issues -- **Documentation**: Check `docs/` folder for detailed guides -- **Code Examples**: Look at existing components for patterns - ---- +## Agent Sub-Documents -## Version History +Read these files proactively based on what you're working on: -| Version | Date | Changes | -|---------|------|---------| -| 1.0.6 | 2026-03-09 | Added Gemini API error classification in `useReportSummary.ts`; added gotcha table for HTTP status mapping; added `useReportSummary.ts` to file organization | -| 1.0.5 | 2026-03-09 | Fixed Report page to use TimeTrackingContext instead of direct localStorage read; added `dayRecordsToArchivedDays()` adapter; added DataService bypass pitfall | -| 1.0.4 | 2026-02-06 | Replaced custom scroll picker with native HTML5 time inputs for better UX and a11y | -| 1.0.3 | 2026-02-06 | Added ScrollTimePicker component, replaced time dropdowns with scroll-wheel UI | -| 1.0.2 | 2026-02-02 | Added auto-open New Task form feature when day starts | -| 1.0.1 | 2025-11-21 | Updated component list, documentation references, and current state | -| 1.0.0 | 2025-11-18 | Initial CLAUDE.md creation | +| When you're working on... | Read this file | +| --------------------------------------------------------------- | ------------------------- | +| Architecture, data flow, auth flow, contexts, DataService | `agents/architecture.md` | +| Naming conventions, TypeScript patterns, UI/styling rules | `agents/conventions.md` | +| Dev setup, npm commands, git workflow, Supabase | `agents/workflow.md` | +| Adding components, pages, context methods, data service methods | `agents/operations.md` | +| Testing, QA checklists, code quality requirements | `agents/testing.md` | +| Debugging, common mistakes, architecture gotchas, Gemini errors | `agents/pitfalls.md` | +| UI/styling rules and Radix component usage | `agents/styles.md` | +| Pull request guidelines | `agents/pull_requests.md` | --- -**Note to AI Assistants**: This document should be your first reference when working on TimeTracker Pro. When in doubt, follow existing patterns and ask clarifying questions rather than making assumptions. +**Note**: When in doubt, follow existing patterns and ask clarifying questions rather than making assumptions. diff --git a/agents/architecture.md b/agents/architecture.md new file mode 100644 index 0000000..6ffda21 --- /dev/null +++ b/agents/architecture.md @@ -0,0 +1,151 @@ +# Architecture — TimeTracker Pro + +## Overall Architecture + +TimeTracker Pro follows a **context-driven architecture** with a **service-oriented data layer**: + +```mermaid +┌─────────────────────────────────────────────────────────┐ +│ App.tsx │ +│ ┌────────────────────────────────────────────────────┐ │ +│ │ AuthProvider (Context) │ │ +│ │ ┌──────────────────────────────────────────────┐ │ │ +│ │ │ TimeTrackingProvider (Context) │ │ │ +│ │ │ │ │ │ +│ │ │ ┌────────────────────────────────────────┐ │ │ │ +│ │ │ │ Pages & Components │ │ │ │ +│ │ │ └────────────────────────────────────────┘ │ │ │ +│ │ └──────────────────────────────────────────────┘ │ │ +│ └────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────┘ + │ + ▼ + ┌───────────────────────┐ + │ DataService Layer │ + │ (Factory Pattern) │ + └───────────────────────┘ + │ │ + ┌───────────┘ └───────────┐ + ▼ ▼ +┌──────────────────┐ ┌──────────────────┐ +│ LocalStorage │ │ Supabase │ +│ Service │ │ Service │ +└──────────────────┘ └──────────────────┘ +``` + +## Key Patterns + +### 1. Context Provider Pattern + +All global state is managed through React Context: + +- `AuthContext` — User authentication and session +- `TimeTrackingContext` — All time tracking operations + +### 2. Service Layer Pattern + +Data persistence is abstracted through the `DataService` interface: + +- **Interface**: `DataService` defines all data operations +- **Implementations**: + - `LocalStorageService` — For guest/offline mode + - `SupabaseService` — For authenticated/cloud mode +- **Factory**: `createDataService(isAuthenticated)` returns appropriate implementation + +### 3. Custom Hook Pattern + +Complex logic is extracted into custom hooks: + +- `useAuth()` — Access authentication state and methods +- `useTimeTracking()` — Access time tracking state and methods +- `useRealtimeSync()` — Real-time sync (currently disabled) + +### 4. Lazy Loading Pattern + +Pages are lazy-loaded for code splitting: + +```typescript +const Index = lazy(() => import('./pages/Index')); +``` + +### 5. Optimistic UI Updates + +UI updates immediately, then syncs to backend: + +```typescript +setTasks(prev => [...prev, newTask]); // Update UI +await dataService.saveCurrentDay(state); // Sync to backend +``` + +--- + +## Data Flow & State Management + +### Authentication Flow + +```md +1. User opens app + ↓ +2. AuthProvider checks for existing session + ↓ +3. If authenticated → Load from Supabase + If guest → Load from localStorage + ↓ +4. AuthContext provides: { user, isAuthenticated, loading, signIn, signUp, signOut } +``` + +### Time Tracking Flow + +```md +1. User starts day (via StartDayDialog) + ↓ +2. TimeTrackingContext updates state + ↓ +3. New Task form auto-opens (defaultOpen prop) + ↓ +4. User creates tasks + ↓ +5. Tasks saved to state (in-memory) + ↓ +6. Manual sync OR critical events (end day, window close) + ↓ +7. DataService persists to localStorage or Supabase +``` + +### User Action → Persistence Flow + +```md +User Action + ↓ +Context Method + ↓ +State Update (in-memory) + ↓ +(Optional) DataService Call + ↓ +localStorage or Supabase +``` + +### Data Service Selection + +```typescript +// Factory pattern selects service based on auth state +const service = createDataService(isAuthenticated); +// Returns: LocalStorageService OR SupabaseService +``` + +### State Management Strategy — Manual Sync (Single-Device Optimized) + +- **No automatic saves** — Saves only on critical events +- **Critical save events**: + 1. Day end (`postDay()`) + 2. Window close (`beforeunload`) + 3. Manual sync button (`forceSyncToDatabase()`) +- **Why?** Optimized for single-device usage, reduces unnecessary database calls +- **Trade-off**: Users must manually sync or complete critical events + +### Data Migration — localStorage ↔ Supabase + +- **Login**: Migrates localStorage data to Supabase (smart merge) +- **Logout**: Syncs Supabase data to localStorage for offline access +- **Logic**: Compares data freshness, prevents overwriting newer data diff --git a/agents/conventions.md b/agents/conventions.md new file mode 100644 index 0000000..31f5a46 --- /dev/null +++ b/agents/conventions.md @@ -0,0 +1,136 @@ +# Conventions — TimeTracker Pro + +## Code Style (CRITICAL) + +⚠️ **These rules MUST be followed — they are project requirements enforced by the linter.** + +### Indentation & Quotes + +- **Tabs, not spaces** — Always use tabs +- **Tab width**: 2 spaces +- **Quotes**: Always double quotes (`""`) — never single quotes (`''`) + +### Component Patterns + +```typescript +// ✅ CORRECT +export const MyComponent = () => { + return ( +
+

Hello World

+
+ ); +}; + +// ❌ WRONG — Uses spaces and single quotes +export const MyComponent = () => { + return ( +
+

Hello World

+
+ ); +}; +``` + +### File Naming + +- **Components**: PascalCase (e.g., `TaskItem.tsx`, `NewTaskForm.tsx`) +- **Hooks**: camelCase with `use` prefix (e.g., `useAuth.tsx`) +- **Utilities**: camelCase (e.g., `timeUtil.ts`) +- **Config**: camelCase (e.g., `categories.ts`) + +### Import Aliases + +```typescript +// ✅ CORRECT — Use @ alias for src imports +import { Task } from '@/contexts/TimeTrackingContext'; +import { Button } from '@/components/ui/button'; + +// ❌ WRONG — Never use relative paths +import { Task } from '../../contexts/TimeTrackingContext'; +``` + +--- + +## UI & Styling Conventions + +### Design System + +- **Follow Radix UI guidelines**: [https://www.radix-ui.com](https://www.radix-ui.com) +- **Use Radix Colors**: [https://www.radix-ui.com/colors](https://www.radix-ui.com/colors) +- **Avoid custom colors** — Use theme variables instead + +### Icons + +1. **Primary**: Radix Icons — [https://www.radix-ui.com/icons](https://www.radix-ui.com/icons) +2. **Fallback**: Lucide — [https://lucide.dev](https://lucide.dev) + +### Spacing & Typography + +- **Follow Radix spacing**: [https://www.radix-ui.com/themes/docs/theme/spacing](https://www.radix-ui.com/themes/docs/theme/spacing) +- **Follow Radix typography**: [https://www.radix-ui.com/themes/docs/theme/typography](https://www.radix-ui.com/themes/docs/theme/typography) +- **Don't use custom spacing or font sizes** — Use theme values + +### Component Usage + +```typescript +// ✅ CORRECT — Using shadcn/ui components +import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent } from "@/components/ui/dialog"; + + + +// ❌ WRONG — Creating custom button styles + +``` + +--- + +## TypeScript Conventions + +### Type Definitions + +```typescript +// Main types defined in contexts +export interface Task { + id: string; + title: string; + description?: string; // Optional fields use ? + startTime: Date; + endTime?: Date; + duration?: number; + project?: string; + client?: string; + category?: string; +} + +// Use Partial<> for updates +updateTask: (taskId: string, updates: Partial) => void; +``` + +### Loose Type Checking + +- `noImplicitAny: false` — Allows implicit any +- `strictNullChecks: false` — Allows null/undefined without explicit checks +- Use types where helpful, but not strictly enforced + +--- + +## Naming Conventions + +### Functions + +- **Actions**: `startDay()`, `endDay()`, `startNewTask()` +- **Getters**: `getTotalDayDuration()`, `getCurrentTaskDuration()` +- **Setters**: `setIsDayStarted()`, `setTasks()` +- **Handlers**: `handleClick()`, `handleSubmit()` + +### State Variables + +- **Boolean**: `isDayStarted`, `isAuthenticated`, `loading`, `isSyncing` +- **Collections**: `tasks`, `projects`, `categories`, `archivedDays` +- **Single items**: `currentTask`, `user`, `dataService` + +### Constants + +- **UPPER_SNAKE_CASE**: `STORAGE_KEYS`, `DEFAULT_CATEGORIES` diff --git a/agents/operations.md b/agents/operations.md new file mode 100644 index 0000000..526b693 --- /dev/null +++ b/agents/operations.md @@ -0,0 +1,230 @@ +# Common Operations — TimeTracker Pro + +## Adding a New Feature Component + +```typescript +// 1. Create component file +// src/components/MyFeature.tsx + +import { useState } from "react"; +import { useTimeTracking } from "@/hooks/useTimeTracking"; +import { Button } from "@/components/ui/button"; + +export const MyFeature = () => { + const { tasks, addTask } = useTimeTracking(); + const [value, setValue] = useState(""); + + return ( +
+ {/* Component content */} +
+ ); +}; + +// 2. Import in page +// src/pages/Index.tsx +import { MyFeature } from "@/components/MyFeature"; +``` + +--- + +## Adding a New Page + +```typescript +// 1. Create page component +// src/pages/MyPage.tsx +import { Navigation } from "@/components/Navigation"; + +const MyPage = () => { + return ( +
+ +
+ {/* Page content */} +
+
+ ); +}; + +export default MyPage; + +// 2. Add route in App.tsx with lazy loading +import { lazy } from "react"; +const MyPage = lazy(() => import("./pages/MyPage")); + +// In Routes: +} /> + +// 3. Add navigation link in Navigation.tsx +``` + +--- + +## Using the TimePicker Component + +The `TimePicker` is a native HTML5 time input wrapped with shadcn/ui styling. + +**Component File**: `src/components/ui/scroll-time-picker.tsx` + +**Props Interface**: + +```typescript +interface TimePickerProps { + value: string; // "HH:MM" 24-hour format (e.g., "14:30") + onValueChange: (value: string) => void; + disabled?: boolean; + className?: string; + id?: string; + 'aria-label'?: string; + 'aria-describedby'?: string; +} +``` + +**Usage Example**: + +```typescript +import { TimePicker } from "@/components/ui/scroll-time-picker"; +import { Label } from "@/components/ui/label"; +import { useState } from "react"; + +const MyComponent = () => { + const [time, setTime] = useState("09:00"); + + return ( +
+ + +
+ ); +}; +``` + +**Key Details**: + +- 15-minute intervals via `step={900}` (`:00`, `:15`, `:30`, `:45`) +- Mobile browsers show native time pickers automatically +- Used in: `StartDayDialog.tsx`, `TaskEditDialog.tsx`, `ArchiveEditDialog.tsx` + +--- + +## Adding a New Context Method + +```typescript +// 1. Define in interface (TimeTrackingContext.tsx) +interface TimeTrackingContextType { + // ... existing methods + myNewMethod: (param: string) => void; +} + +// 2. Implement in provider +const myNewMethod = (param: string) => { + // Implementation +}; + +// 3. Export in value object +return ( + + {children} + +); + +// 4. Use in components +const { myNewMethod } = useTimeTracking(); +myNewMethod("test"); +``` + +--- + +## Adding a Data Service Method + +```typescript +// 1. Add to interface (dataService.ts) +export interface DataService { + // ... existing methods + myDataOperation: (data: MyData) => Promise; +} + +// 2. Implement in LocalStorageService +class LocalStorageService implements DataService { + async myDataOperation(data: MyData): Promise { + localStorage.setItem('my_key', JSON.stringify(data)); + } +} + +// 3. Implement in SupabaseService +class SupabaseService implements DataService { + async myDataOperation(data: MyData): Promise { + const user = await getCachedUser(); + await supabase.from('my_table').insert(data); + } +} +``` + +--- + +## Modifying Database Schema + +```typescript +// 1. Create Supabase migration +// supabase/migrations/YYYYMMDD_description.sql +ALTER TABLE tasks ADD COLUMN new_field TEXT; + +// 2. Update TypeScript types (TimeTrackingContext.tsx) +export interface Task { + // ... existing fields + newField?: string; +} + +// 3. Update dataService.ts to save/load new field +const taskData = { + // ... existing fields + new_field: task.newField, +}; +``` + +--- + +## AI Task Checklists + +### Add a new task property + +1. Update `Task` interface in `src/contexts/TimeTrackingContext.tsx` +2. Update task creation in `startNewTask()` +3. Update database schema if using Supabase +4. Update `src/services/dataService.ts` to save/load new property +5. Update UI components to display/edit property +6. Test in both guest and authenticated modes + +### Add a new page + +1. Create page component in `src/pages/` +2. Add route in `App.tsx` with lazy loading +3. Add navigation link in `Navigation.tsx` +4. Follow existing page layout patterns +5. Test routing and navigation + +### Fix a bug + +1. **Reproduce**: Understand the bug completely +2. **Locate**: Find the relevant code +3. **Fix**: Make minimal changes +4. **Test**: Verify fix in both guest and authenticated modes +5. **Document**: Add comments if logic is complex + +### Add export/import functionality + +1. Study existing `exportToCSV()` and `importFromCSV()` +2. Follow the exact CSV schema format +3. Handle errors gracefully +4. Validate data before import +5. Test with sample data files in `tests/` directory diff --git a/agents/pitfalls.md b/agents/pitfalls.md new file mode 100644 index 0000000..e0c6500 --- /dev/null +++ b/agents/pitfalls.md @@ -0,0 +1,163 @@ +# Pitfalls & Gotchas — TimeTracker Pro + +## Common Code Mistakes + +### 1. Using Spaces Instead of Tabs + +```typescript +// ❌ WRONG +export const Component = () => { + return
Content < /div>; / / spaces; +}; + +// ✅ CORRECT +export const Component = () => { + return
Content < /div>; / / tabs; +}; +``` + +### 2. Using Single Quotes + +```typescript +// ❌ WRONG +const message = 'Hello World'; + +// ✅ CORRECT +const message = 'Hello World'; +``` + +### 3. Not Using @ Alias + +```typescript +// ❌ WRONG +import { Task } from '../../contexts/TimeTrackingContext'; + +// ✅ CORRECT +import { Task } from '@/contexts/TimeTrackingContext'; +``` + +### 4. Creating Custom Colors + +```typescript +// ❌ WRONG +
Content
+ +// ✅ CORRECT +
Content
+``` + +### 5. Forgetting to Save Data + +```typescript +// ❌ WRONG — Data not persisted +setTasks([...tasks, newTask]); + +// ✅ CORRECT — Explicitly sync +setTasks([...tasks, newTask]); +await forceSyncToDatabase(); // Or wait for critical event +``` + +### 6. Bypassing the DataService + +```typescript +// ❌ WRONG — Reads localStorage only; breaks for authenticated users +// whose data lives in Supabase +const raw = localStorage.getItem('timetracker_archived_days'); + +// ✅ CORRECT — Use the context, which routes through the right service +const { archivedDays } = useTimeTracking(); +``` + +Any utility that needs archived days must consume the context or accept +`DayRecord[]` as a parameter. Use `dayRecordsToArchivedDays()` from +`src/utils/reportUtils.ts` to convert to the `ArchivedDay[]` shape. + +--- + +## Architecture Gotchas + +### 1. Manual Sync Required + +- **Issue**: Data doesn't auto-save on every change +- **Solution**: Use `forceSyncToDatabase()` or trigger critical events +- **Why**: Optimized for single-device usage + +### 2. Category Lookup by ID + +```typescript +// ❌ WRONG — Looking up by name +const category = categories.find(c => c.name === task.category); + +// ✅ CORRECT — Looking up by ID +const category = categories.find(c => c.id === task.category); +``` + +### 3. Date Handling + +```typescript +// ❌ WRONG — Date as string +const startTime = '2024-11-18'; + +// ✅ CORRECT — Date object +const startTime = new Date('2024-11-18'); +``` + +### 4. Supabase User Caching + +```typescript +// ❌ WRONG — Repeated auth calls (slow) +const { + data: { user } +} = await supabase.auth.getUser(); + +// ✅ CORRECT — Use cached user helper +const user = await getCachedUser(); +``` + +### 5. Gemini API Error Classification + +Do **not** surface Gemini's raw `error.message` to the user — it is often vague +and gives no guidance on whether to wait, fix a key, or switch plans. + +Always classify by HTTP status + `error.status` using `classifyGeminiError()` +in `src/hooks/useReportSummary.ts`: + +| Symptom | HTTP | Gemini status | Meaning | +| ----------------------------- | ---- | ------------------------------ | ------------------------------------ | +| Multiple consecutive failures | 503 | `UNAVAILABLE` | Server overloaded — retry in seconds | +| First request of day fails | 429 | `RESOURCE_EXHAUSTED` + "quota" | Daily free-tier limit hit | +| Rapid retries fail | 429 | `RESOURCE_EXHAUSTED` + "rate" | Per-minute RPM limit — wait 30–60s | +| Always fails | 403 | `PERMISSION_DENIED` | Bad API key | +| Always fails in region | 400 | `FAILED_PRECONDITION` | Free tier not available in region | + +Also handle `finishReason` on 200 OK responses: a `SAFETY` or `RECITATION` +block returns HTTP 200 with empty `text` — use `classifyFinishReason()`. + +--- + +## Performance Gotchas + +### 1. Avoiding Unnecessary Re-renders + +- Use `useCallback` for stable function references +- Use `useRef` for values that don't need to trigger re-renders +- Context updates trigger all consumers — keep context lean + +### 2. Lazy Loading + +- Pages are lazy-loaded — don't preload unnecessarily +- Always wrap lazy components in `` with a fallback + +--- + +## AI Self-Check Before Making Changes + +- [ ] Did I read the relevant context file first? (`TimeTrackingContext.tsx` or `AuthContext.tsx`) +- [ ] Did I read `dataService.ts` if touching data persistence? +- [ ] Did I check existing patterns in similar components? +- [ ] Am I using tabs and double quotes? +- [ ] Am I using `@/` import aliases? +- [ ] Am I using shadcn/ui components (not raw HTML with custom styles)? +- [ ] Will this work in both guest and authenticated modes? +- [ ] Did I update the data service if persistence is involved? +- [ ] Will `npm run lint` and `npm run build` pass? diff --git a/agents/pull_requests.md b/agents/pull_requests.md index 82280ea..ce81bfe 100644 --- a/agents/pull_requests.md +++ b/agents/pull_requests.md @@ -1,5 +1,15 @@ -# Pull Requests +# Pull Requests — TimeTracker Pro -- Always have a title and description that clearly explains the purpose of the PR. -- Wait until all checks have been completed before suggesting that a PR be merged. -- Add appropriate Labels to any PR. +## Title Format + +```text +[TimeTrackerPro] +``` + +## Requirements + +- Always include a clear title and description explaining the purpose of the PR +- Keep your branch rebased (not merged) against the base branch +- Run `npm run lint` and `npm run build` before committing — both must pass +- Wait until all checks have completed before suggesting a PR be merged +- Add appropriate labels to every PR diff --git a/agents/styles.md b/agents/styles.md index 55f53d4..36d5767 100644 --- a/agents/styles.md +++ b/agents/styles.md @@ -1,6 +1,6 @@ -# Styles +# Styles — TimeTracker Pro -The following rules are to govern the style choices for Agents. See [Agents.md](../AGENTS.md) for detailed configurations. +The following rules govern style choices for UI and visual design. ## Library diff --git a/agents/testing.md b/agents/testing.md new file mode 100644 index 0000000..fcec05e --- /dev/null +++ b/agents/testing.md @@ -0,0 +1,63 @@ +# Testing & Quality — TimeTracker Pro + +## Running Tests + +```bash +# Unit tests +npm run test + +# Linting +npm run lint + +# Type checking (via build) +npm run build +``` + +--- + +## Manual Testing Checklist + +**Before submitting any change:** + +- [ ] Test in guest mode (no authentication) +- [ ] Test in authenticated mode +- [ ] Test on mobile viewport +- [ ] Test data persistence (refresh page) +- [ ] Test export/import functionality if relevant +- [ ] Verify no console errors +- [ ] Check responsive design + +--- + +## PWA-Specific Testing + +- [ ] Service worker registers successfully (DevTools → Application → Service Workers) +- [ ] App works offline (DevTools → Network → Offline) +- [ ] Install prompt appears (wait 30 seconds or test manually) +- [ ] App installs correctly on desktop (Chrome/Edge) +- [ ] Bottom navigation visible on mobile viewports +- [ ] Touch targets are large enough (44×44px minimum) +- [ ] Manifest loads without errors (DevTools → Application → Manifest) +- [ ] Update notification works when service worker updates + +--- + +## Code Quality Requirements + +1. **All lint errors must be fixed** before committing — run `npm run lint` +2. **All TypeScript errors must be fixed** before merging — run `npm run build` +3. **Manual testing** of changed functionality required +4. **No breaking changes** without documentation + +--- + +## Pre-Commit Checklist + +Before every commit, verify: + +- [ ] `npm run lint` passes with no errors +- [ ] `npm run build` passes with no type errors +- [ ] Tabs (not spaces) used throughout +- [ ] Double quotes used throughout +- [ ] `@/` import aliases used (no relative paths) +- [ ] Changed functionality tested manually diff --git a/agents/workflow.md b/agents/workflow.md new file mode 100644 index 0000000..588931b --- /dev/null +++ b/agents/workflow.md @@ -0,0 +1,98 @@ +# Development Workflow — TimeTracker Pro + +## Initial Setup + +```bash +# Clone repository +git clone +cd TimeTrackerPro + +# Install dependencies +npm install + +# Setup environment (optional — for cloud sync) +cp .env.example .env +# Edit .env with your Supabase credentials + +# Start development server +npm run dev +# Opens on http://localhost:8080 +``` + +## Available Commands + +```bash +# Development +npm run dev # Start dev server (localhost:8080) +npm run build # Build for production +npm run build:dev # Build with development mode +npm run preview # Preview production build + +# Code Quality +npm run lint # Run ESLint +npm run test # Run Vitest tests + +# Testing Scripts +npm run test-full-import # Test full CSV import +npm run test-error-handling # Test CSV error handling +npm run test-csv-import # Test standard CSV import + +# PWA Screenshot Generation +npm run screenshots:install # Install Playwright browsers (first time only) +npm run screenshots # Capture PWA screenshots (headless) +npm run screenshots:headed # Capture screenshots with visible browser +``` + +**PWA Screenshot Usage:** + +1. `npm run screenshots:install` — Install Playwright browsers (~300MB, one-time) +2. `npm run dev` — Start dev server (keep running) +3. `npm run screenshots` — Generate screenshots in new terminal +4. Screenshots saved to `public/screenshots/` + +See `tests/SCREENSHOTS_README.md` for detailed documentation. + +--- + +## Git Workflow + +### Branch Naming + +- Feature branches: `claude/claude-md--` +- Always work on designated branch from session instructions + +### Commit Messages + +```bash +# Format: : +# Types: feat, fix, refactor, docs, style, test, chore + +git commit -m "feat: add billable category option" +git commit -m "fix: data recovery issues" +git commit -m "refactor: improve data service caching" +``` + +### Creating Pull Requests + +1. **Title Format**: `[TimeTrackerPro] ` +2. **Description**: Clear explanation of changes +3. **Wait for checks**: Don't merge until all tests pass +4. **Add labels**: Appropriate PR labels +5. **See**: `agents/pull_requests.md` for full guidelines + +--- + +## Working with Supabase + +### Environment Setup + +```bash +# .env file (never commit this!) +VITE_SUPABASE_URL=https://your-project.supabase.co +VITE_SUPABASE_ANON_KEY=your-anon-key +``` + +### Database Schema Location + +- Schema definitions: `supabase/migrations/` +- See `docs/SCHEMA_COMPATIBILITY.md` for schema history