Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,127 changes: 50 additions & 1,077 deletions CLAUDE.md

Large diffs are not rendered by default.

151 changes: 151 additions & 0 deletions agents/architecture.md
Original file line number Diff line number Diff line change
@@ -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
136 changes: 136 additions & 0 deletions agents/conventions.md
Original file line number Diff line number Diff line change
@@ -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 (
<div className="container">
<p>Hello World</p>
</div>
);
};

// ❌ WRONG — Uses spaces and single quotes
export const MyComponent = () => {
return (
<div className='container'>
<p>Hello World</p>
</div>
);
};
```

### 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";

<Button variant="default">Save</Button>

// ❌ WRONG — Creating custom button styles
<button className="bg-blue-500 px-4 py-2">Save</button>
```

---

## 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<Task>) => 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`
Loading
Loading