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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Links

- [Unreleased Changes](https://github.com/AdamJ/TimeTrackerPro/compare/v0.21.1...HEAD)
- [Unreleased Changes](https://github.com/AdamJ/TimeTrackerPro/compare/v0.54.0...HEAD)
- [Version 0.54.0](https://github.com/AdamJ/TimeTrackerPro/releases/tag/v0.54.0)
- [Version 0.21.1](https://github.com/AdamJ/TimeTrackerPro/releases/tag/v0.21.1)
16 changes: 8 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# CLAUDE.md - AI Assistant Codebase Guide

**Last Updated:** 2026-05-14
**Version:** 2.3.0
**Last Updated:** 2026-05-26
**Version:** 2.4.0

Timetraked is a React 18 + TypeScript time tracking PWA for freelancers and consultants, with dual storage (localStorage guest mode and optional Supabase cloud sync). A native iOS app is also available via Capacitor.

Expand All @@ -23,7 +23,7 @@ After implementing changes, run lint and tests before considering a task complet

| Layer | Technology |
| ------------ | ------------------------------------------- |
| UI Framework | React 18 + TypeScript 5.8 |
| UI Framework | React 18 + TypeScript 5.9 |
| Build | Vite 5 + SWC |
| Routing | React Router 6 |
| Styling | Tailwind CSS 3 + Radix UI + shadcn/ui |
Expand Down Expand Up @@ -64,8 +64,10 @@ export const MyComponent = () => {

| 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/TimeTrackingContext.tsx` | Main application state and logic (1200+ lines) |
| `src/services/dataService.ts` | Data persistence factory — returns `LocalStorageService` or `SupabaseService` |
| `src/services/supabaseService.ts` | Supabase data persistence implementation (1100+ lines) |
| `src/services/localStorageService/` | localStorage data persistence implementation (split into per-entity modules) |
| `src/contexts/AuthContext.tsx` | Authentication state management |
| `src/lib/supabase.ts` | Supabase client configuration and caching |
| `src/config/categories.ts` | Default category definitions |
Expand All @@ -74,9 +76,7 @@ export const MyComponent = () => {
| `src/components/IosPageHeader.tsx` | iOS-only sticky nav bar with safe-area-inset-top, back chevron, and action slot |
| `src/components/ui/adaptive-dialog.tsx` | Renders vaul `Drawer` on iOS, Radix `Dialog` on web |
| `src/hooks/useHaptics.ts` | `@capacitor/haptics` wrapper (light/medium/heavy, success/error) |
| `src/hooks/useStatusBar.ts` | `@capacitor/status-bar` wrapper — syncs bar style with dark/light mode |
| `src/hooks/useAppLifecycle.ts` | `@capacitor/app` appStateChange hook for reliable background persistence |
| `src/hooks/useKeyboardHeight.ts` | `@capacitor/keyboard` reactive height for bottom-sheet form padding |
| `src/hooks/useLongPress.ts` | 500 ms hold detector for context menu trigger on touch |
| `capacitor.config.ts` | Capacitor iOS configuration (Keyboard resize plugin configured here) |
| `.env.ios` | iOS build env (VITE_IOS_BUILD=true, no Supabase) |
Expand Down Expand Up @@ -104,7 +104,7 @@ The app ships as both a PWA and a native iOS app via Capacitor 8.
- Haptic feedback fires on every meaningful interaction via `useHaptics`
- `@capacitor/app` `appStateChange` event used for emergency data persistence (more reliable than `visibilitychange`)
- `@capacitor/status-bar` syncs status bar text colour with system dark/light mode
- `@capacitor/keyboard` configured with `resize: body`; `useKeyboardHeight` lifts bottom-sheet content above the keyboard
- `@capacitor/keyboard` configured with `resize: body`; viewport shrinks above the keyboard so bottom-sheet form fields stay accessible
- Long-press on task cards opens a context menu (Edit / Delete); on-card action buttons are hidden

**Installed Capacitor plugins** (all v8.x):
Expand Down
71 changes: 47 additions & 24 deletions README-EXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ See [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md) and [docs/SECURITY.md](docs

| Category | Technology |
| ------------ | ------------------------------------------- |
| UI Framework | React 18 + TypeScript 5.8 |
| UI Framework | React 18 + TypeScript 5.9 |
| Build | Vite 5 + SWC |
| Routing | React Router 6 |
| Styling | Tailwind CSS 3 + Radix UI + shadcn/ui |
Expand Down Expand Up @@ -287,8 +287,12 @@ const service = createDataService(isAuthenticated);
#### 3. Custom Hooks Pattern

- `useAuth()` — authentication state and methods
- `useTimeTracking()` — time tracking operations
- `useOffline()` — offline queue management
- `useTimeTracking()` — time tracking state and operations
- `useHaptics()` — Capacitor haptic feedback (no-op on web)
- `useAppLifecycle()` — Capacitor app background/foreground events
- `useLongPress()` — 500 ms hold detector for touch context menus
- `useReportStorage()` — persists and restores generated AI report summaries
- `useReportSummary()` — calls Gemini API to generate weekly summaries

### Data Flow

Expand Down Expand Up @@ -325,7 +329,7 @@ Precache: App shell (HTML, CSS, JS, icons)
```text
src/
├── components/
│ ├── ui/ # Base components (49 files)
│ ├── ui/ # Base components (49+ files, including adaptive-dialog)
│ ├── ArchiveEditDialog.tsx
│ ├── ArchiveFilter.tsx
│ ├── ArchiveItem.tsx
Expand All @@ -335,46 +339,65 @@ src/
│ ├── DeleteConfirmationDialog.tsx
│ ├── ExportDialog.tsx
│ ├── InstallPrompt.tsx
│ ├── IosPageHeader.tsx # iOS-only sticky nav bar
│ ├── KanbanBoard.tsx # Kanban planning board
│ ├── KanbanColumn.tsx
│ ├── MarkdownDisplay.tsx
│ ├── MobileNav.tsx
│ ├── Navigation.tsx
│ ├── NewTaskForm.tsx
│ ├── PageLayout.tsx # Shared page chrome
│ ├── PlannedTaskCard.tsx
│ ├── PlannedTaskDialog.tsx
│ ├── ProjectManagement.tsx
│ ├── StaleDayDialog.tsx
│ ├── StartDayDialog.tsx
│ ├── SummaryOutput.tsx
│ ├── SyncStatus.tsx
│ ├── TaskEditDialog.tsx
│ ├── TaskItem.tsx
│ ├── TaskTrackingPanel.tsx
│ ├── UpdateNotification.tsx
│ └── UserMenu.tsx
├── config/
│ ├── categories.ts # Default categories
│ └── projects.ts # Default projects
│ ├── categories.ts # Default categories
│ └── projects.ts # Default projects
├── contexts/
│ ├── AuthContext.tsx
│ ├── TimeTrackingContext.tsx
│ └── OfflineContext.tsx
│ ├── OfflineContext.tsx # Online/offline detection and toasts
│ └── TimeTrackingContext.tsx
├── hooks/
│ ├── use-mobile.tsx
│ ├── use-toast.tsx
│ ├── useAppLifecycle.ts # @capacitor/app background persistence
│ ├── useAuth.tsx
│ ├── useTimeTracking.tsx
│ ├── useOffline.tsx
│ └── use-toast.tsx
│ ├── useHaptics.ts # @capacitor/haptics wrapper
│ ├── useLongPress.ts # 500 ms hold detector
│ ├── useReportStorage.ts # Persist generated report summaries
│ ├── useReportSummary.ts # Gemini AI summary generation
│ └── useTimeTracking.tsx
├── lib/
│ ├── supabase.ts # Supabase client
│ └── utils.ts # Helper functions
│ ├── supabase.ts # Supabase client and call telemetry
│ └── utils.ts # Helper functions
├── pages/
│ ├── Index.tsx # Dashboard (start/end day, stats)
│ ├── TaskList.tsx # Active task list and NewTaskForm
│ ├── Archive.tsx # Archived days
│ ├── ProjectList.tsx # Project management
│ ├── Categories.tsx # Category management
│ ├── Report.tsx # AI weekly summary
│ ├── Settings.tsx # App settings
│ └── NotFound.tsx # 404 page
│ ├── Archive.tsx # Archived days
│ ├── Categories.tsx # Category management
│ ├── Index.tsx # Dashboard (start/end day, stats)
│ ├── NotFound.tsx # 404 page
│ ├── ProjectList.tsx # Project management
│ ├── Report.tsx # AI weekly summary
│ ├── Settings.tsx # App settings
│ └── TaskList.tsx # Active task list and NewTaskForm
├── services/
│ └── dataService.ts # Persistence abstraction
│ ├── dataService.ts # Factory — returns LocalStorage or Supabase impl
│ ├── localStorageService/ # localStorage implementation (per-entity modules)
│ └── supabaseService.ts # Supabase implementation (1100+ lines)
├── utils/
│ ├── timeUtil.ts # Time formatting
│ └── reportUtils.ts # Report grouping and formatting
│ ├── calculationUtils.ts # Revenue and hours calculations
│ ├── checklistUtils.ts # GFM checklist extraction
│ ├── exportUtils.ts # CSV import/export
│ ├── reportUtils.ts # Report grouping and formatting
│ └── timeUtil.ts # Time formatting
├── App.tsx
└── main.tsx
```
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,11 @@ See [CHANGELOG.md](CHANGELOG.md) for the full history of changes.

**Recent highlights:**

- `PageLayout` shared component standardizes page chrome across all pages
- Incomplete checklist items carry over as todo tasks when archiving a day
- **Kanban planning board** — drag-and-drop task planning view (`KanbanBoard`, `KanbanColumn`, `PlannedTaskCard`)
- Apple HIG pass for native iOS: bottom sheets, haptic feedback, status bar theming, page transitions, and long-press context menus
- Persistent report summaries saved to localStorage; markdown preview/export in the report output panel
- Weekly Report distinguishes Gemini API failure modes (rate limit, quota, overload, key issues)
- Fixed Weekly Report for authenticated users (data sourced from Supabase)
- `PageLayout` shared component standardizes page chrome across all pages

---

Expand Down
Loading