# Carry Your Live - Mobile To-Do & Calendar App A minimalist, offline-first task management app built with Expo, React Native, and WatermelonDB. Features multiple screens with bottom navigation, social features, and a full-featured backend API. ## πŸ“ Recent Progress (v1.1.0 - Unreleased) ### Added - **Friends feature**: Friend requests, accept/decline/remove, user search, full backend routes - **Assignee field on tasks**: Schema v7, model, types, forms, sync, task actions - **AssigneeSelector component** and assignee display in TaskItem - **QuickAddBar** on tasks overview (copied from calendar) - **Backend**: Mounted friends route, added assigneeId to task validation and sync ### Changed - Due date prefilled from Calendar "+" button - 12-hour time formatting across task rows and pickers - Calendar strip scrolls to selected day when navigating months - Calendar completion toggle now handles repeating tasks and reminders - Task color strips now use the task's category color ### Fixed - WheelTimePicker FlatList scroll clamping - all hours (0-23) and minutes (0-59) reachable - WheelTimePicker selection highlight background connecting selected item with colon separator - WheelTimePicker number alignment in scroll list - Tasks without a due date no longer get overdue styling - `useOverdueTasks` infinite re-subscription loop (Date.now in effect deps) - Web/Android crashes from decorator transform ordering (babel config) - FormButtons crash outside FormProvider; Cancel navigation fallback - Task repeat settings, reminders and series info now sync to backend ### Removed - Task color picker (task color now comes from its category) - Drag lift popup from TaskItem (scale + shadow on drag) - Checkbox from task items - Selection bar overlapping QuickAddBar on tasks overview --- ## Features ### Core Functionality - **Offline-First Architecture**: Full CRUD operations work offline with WatermelonDB + SQLite - **Auto-Sync**: Background synchronization with custom Postgres API when online - **Cross-Platform**: iOS, Android, and Web from single codebase - **Desktop Support**: Electron wrapper for desktop app distribution ### Screens #### 1. Tasks Screen (To-Do List) - **Header**: App logo + "TODO" title with rounded corners - **Category Filter**: Horizontal scrollable chips (Work, Personal, School, Shopping, Health, Finance, All) - Single selection with visual feedback (thicker border, shadow, scale animation) - Instant task filtering - **QuickAddBar**: Quick task creation from list view - **Task List**: Virtualized FlatList with sections (Pending/Completed) - Task title (truncated with ellipsis) - Three-dot overflow menu (Edit, Delete, Duplicate, Mark Complete, Change Category, Change Priority) - Priority badges with colors - Due date/time with overdue/due-today highlighting - Category color indicator strip - Assignee display - Swipe actions (left: delete, right: complete) - Drag-to-reorder with visual drop indicators - Long press β†’ Selection mode (multi-delete, multi-complete, change category/priority) - **Floating Action Button**: Bottom-right, opens Add Task screen #### 2. Calendar Screen - **Date Strip**: Horizontal scrollable days of current month - Current day highlighted, scrolls to selected day on month change - **Month Label**: Centered (e.g., "JAN 2026") - **QuickAddBar**: Quick task creation for selected date - **Task List**: Tasks for selected day with category color, title, time, completion status - **Analog Clock Widget**: Decorative analog clock display - **Empty State**: "No tasks scheduled." - **Day View**: Detailed view for selected day (pushes to stack) #### 3. Stats Screen - Client-side statistics (`useStats` hook) - Task completion metrics - Category and priority breakdowns #### 4. Settings Screen - **Account**: Login/Register/Sign Out (SyncModal) - **Server URL Override**: Custom API endpoint configuration - **Appearance**: Accent color picker (dark mode toggle planned) - **Task Defaults**: Default category, sort order (Date, Priority, Alphabetically, Creation Date), show completed toggle - **Calendar**: Days ahead to display - **Reminders**: Global reminder preference (stored, wiring in progress) - **Notifications**: Toggle (stored, wiring in progress) - **Legal**: Privacy Policy, Terms of Service - **About**: Version info #### 5. Add New Task Screen - **Category Selector**: Horizontal row of colored circles (required) - **Task Name**: Single-line input, 100 char max (required) - **Subtasks**: Unlimited, add/remove individually, nested subtask support - **Date & Time**: Date picker, time picker (WheelTimePicker), calendar button - **Priority**: Dropdown (None, Low, Medium, High, Critical) with color indicators - **Repeat Profile**: Recurring task configuration - **Reminder**: Reminder offset selector - **Assignee**: Assign task to friend - **Description**: Multi-line text area, 1000 char max - **Bottom Actions**: Submit (primary) / Cancel (secondary) fixed buttons #### 6. Task Detail Screen - Full task view with all fields - Subtask management (add, complete, reorder, convert to task) - Edit functionality - Repeat profile configuration #### 7. Subtask Detail Screen - Nested subtask management - Convert subtask ↔ task - Re-parent subtasks #### 8. Sync Modal - Login/Register forms - Forgot/Reset password flow - Server URL configuration - Sync status display ### Task Features - **Nested Subtasks**: Unlimited depth, re-parenting, drag reorder - **Repeating Tasks**: Repeat profiles, series IDs, this/future/all delete scopes, undo-complete - **Categories/Tags**: 6 default categories with colors, custom category editor - **Priorities**: None, Low, Medium, High, Critical with color badges - **Due Dates/Times**: With all-day option - **Reminders**: Per-task reminder offsets - **Assignees**: Assign tasks to friends - **Overdue/Due Today**: Visual highlighting ### Social Features - **Friends System**: Send/accept/decline/remove friend requests - **User Search**: Find users by username/email - **Task Assignment**: Assign tasks to friends (client-side, backend schema ready) --- ## Tech Stack | Layer | Technology | |-------|------------| | Framework | Expo (React Native) / Expo Router v3 | | Language | TypeScript (strict mode) | | Navigation | Expo Router (file-based) | | Database | WatermelonDB + SQLite (expo-sqlite) | | State | WatermelonDB reactive queries (no Redux) | | Forms | React Hook Form + Zod validation | | UI Components | React Native Paper + Custom components | | Animations | React Native Reanimated v3 | | Date/Time | @react-native-community/datetimepicker + date-fns + WheelTimePicker | | Build | EAS Build / Gradle (local APK) / Electron Builder (desktop) | | CI/CD | Gitea Actions (`.gitea/workflows/build-apk.yml`) | | Backend | Node.js + Express + TypeScript | | Backend DB | PostgreSQL + Drizzle ORM | | Auth | JWT (access + refresh tokens) | | Validation | Zod (shared with frontend) | --- ## Project Structure ``` carry-your-live/ β”œβ”€β”€ app/ β”‚ β”œβ”€β”€ _layout.tsx # Root layout + DatabaseProvider + AuthProvider β”‚ β”œβ”€β”€ (tabs)/ β”‚ β”‚ β”œβ”€β”€ _layout.tsx # Bottom tab navigator β”‚ β”‚ β”œβ”€β”€ index.tsx # Tasks screen β”‚ β”‚ β”œβ”€β”€ calendar.tsx # Calendar screen β”‚ β”‚ β”œβ”€β”€ stats.tsx # Stats screen β”‚ β”‚ └── settings.tsx # Settings screen β”‚ β”œβ”€β”€ add-task.tsx # Add Task screen β”‚ β”œβ”€β”€ day-view.tsx # Calendar day detail β”‚ β”œβ”€β”€ task-detail.tsx # Task view/edit β”‚ └── subtask-detail.tsx # Subtask view/edit β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ components/ # Reusable UI components (30+) β”‚ β”‚ β”œβ”€β”€ Header.tsx β”‚ β”‚ β”œβ”€β”€ CategoryFilter.tsx β”‚ β”‚ β”œβ”€β”€ TaskList.tsx β”‚ β”‚ β”œβ”€β”€ TaskItem.tsx β”‚ β”‚ β”œβ”€β”€ FloatingActionButton.tsx β”‚ β”‚ β”œβ”€β”€ CategorySelector.tsx β”‚ β”‚ β”œβ”€β”€ TaskNameInput.tsx β”‚ β”‚ β”œβ”€β”€ SubtasksSection.tsx β”‚ β”‚ β”œβ”€β”€ DateTimePicker.tsx β”‚ β”‚ β”œβ”€β”€ PrioritySelector.tsx β”‚ β”‚ β”œβ”€β”€ DescriptionInput.tsx β”‚ β”‚ β”œβ”€β”€ FormButtons.tsx β”‚ β”‚ β”œβ”€β”€ ListItem.tsx β”‚ β”‚ β”œβ”€β”€ AnalogClock.tsx β”‚ β”‚ β”œβ”€β”€ AssigneeSelector.tsx β”‚ β”‚ β”œβ”€β”€ CategoryEditorModal.tsx β”‚ β”‚ β”œβ”€β”€ ColorPickerInput.tsx β”‚ β”‚ β”œβ”€β”€ ColorWheel.tsx β”‚ β”‚ β”œβ”€β”€ DateTimeInput.tsx β”‚ β”‚ β”œβ”€β”€ ForgotPasswordModal.tsx β”‚ β”‚ β”œβ”€β”€ FriendsModal.tsx β”‚ β”‚ β”œβ”€β”€ LegalModal.tsx β”‚ β”‚ β”œβ”€β”€ OptionPickerModal.tsx β”‚ β”‚ β”œβ”€β”€ QuickAddBar.tsx β”‚ β”‚ β”œβ”€β”€ ReminderSelector.tsx β”‚ β”‚ β”œβ”€β”€ RepeatSelector.tsx β”‚ β”‚ β”œβ”€β”€ ServerUrlModal.tsx β”‚ β”‚ β”œβ”€β”€ SubtaskItem.tsx β”‚ β”‚ β”œβ”€β”€ SyncModal.tsx β”‚ β”‚ β”œβ”€β”€ SyncStatus.tsx β”‚ β”‚ β”œβ”€β”€ TabBarIcon.tsx β”‚ β”‚ β”œβ”€β”€ TaskDeleteModal.tsx β”‚ β”‚ β”œβ”€β”€ TaskOverflowMenu.tsx β”‚ β”‚ β”œβ”€β”€ UpdateNotifier.tsx β”‚ β”‚ └── WheelTimePicker.tsx β”‚ β”œβ”€β”€ constants/ β”‚ β”‚ └── index.ts # Categories, priorities, colors, reminder options β”‚ β”œβ”€β”€ database/ β”‚ β”‚ β”œβ”€β”€ schema.ts # WatermelonDB schema (v21) β”‚ β”‚ β”œβ”€β”€ index.ts # Database instance + collections β”‚ β”‚ β”œβ”€β”€ sync.ts # Custom API sync adapter (25KB) β”‚ β”‚ β”œβ”€β”€ migrations.ts # Schema migrations β”‚ β”‚ β”œβ”€β”€ adapter.ts # Platform-specific adapters β”‚ β”‚ └── tombstones.ts # Deleted record tracking β”‚ β”œβ”€β”€ hooks/ β”‚ β”‚ β”œβ”€β”€ useDatabase.tsx # Database context & providers β”‚ β”‚ β”œβ”€β”€ useTasks.tsx # Task queries with reactive state β”‚ β”‚ β”œβ”€β”€ useCategories.tsx # Category queries β”‚ β”‚ β”œβ”€β”€ useTasksByDate.tsx # Calendar date queries β”‚ β”‚ β”œβ”€β”€ useFriends.tsx # Friends state & actions β”‚ β”‚ β”œβ”€β”€ useAuth.tsx # Authentication state β”‚ β”‚ └── useStats.tsx # Statistics computation β”‚ β”œβ”€β”€ models/ β”‚ β”‚ β”œβ”€β”€ Task.ts # Task model (assigneeId, repeat, reminders) β”‚ β”‚ β”œβ”€β”€ Category.ts β”‚ β”‚ β”œβ”€β”€ Subtask.ts β”‚ β”‚ β”œβ”€β”€ RepeatProfile.ts β”‚ β”‚ β”œβ”€β”€ Friendship.ts β”‚ β”‚ └── Tombstone.ts β”‚ β”œβ”€β”€ services/ β”‚ β”‚ β”œβ”€β”€ api.ts # API client with auth β”‚ β”‚ β”œβ”€β”€ auth.ts # Auth token management β”‚ β”‚ β”œβ”€β”€ friends.ts # Friends API calls β”‚ β”‚ β”œβ”€β”€ notifications.ts # Reminder scheduling (expo-notifications) β”‚ β”‚ β”œβ”€β”€ repeat.ts # Repeat task generation β”‚ β”‚ └── taskActions.ts # Task CRUD + sync operations β”‚ β”œβ”€β”€ theme/ β”‚ β”‚ β”œβ”€β”€ index.ts # Theme context, colors, spacing β”‚ β”‚ └── theme.tsx # Accent color picker, settings sync β”‚ β”œβ”€β”€ types/ β”‚ β”‚ └── index.ts # TypeScript interfaces β”‚ └── utils/ β”‚ β”œβ”€β”€ date.ts # Date formatting utilities β”‚ β”œβ”€β”€ format.ts # General formatting β”‚ └── validation.ts # Zod schemas β”œβ”€β”€ backend/ # Backend API (separate package) β”‚ β”œβ”€β”€ src/ β”‚ β”‚ β”œβ”€β”€ index.ts # Express app entry β”‚ β”‚ β”œβ”€β”€ db/ β”‚ β”‚ β”‚ β”œβ”€β”€ schema.ts # Drizzle schema (Postgres) β”‚ β”‚ β”‚ └── index.ts # DB connection β”‚ β”‚ β”œβ”€β”€ routes/ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.ts # Register, login, me, forgot/reset password β”‚ β”‚ β”‚ β”œβ”€β”€ categories.ts # Category CRUD β”‚ β”‚ β”‚ β”œβ”€β”€ tasks.ts # Task CRUD + batch β”‚ β”‚ β”‚ β”œβ”€β”€ subtasks.ts # Subtask CRUD β”‚ β”‚ β”‚ β”œβ”€β”€ sync.ts # Pull/push sync endpoints β”‚ β”‚ β”‚ β”œβ”€β”€ users.ts # User profile & settings β”‚ β”‚ β”‚ β”œβ”€β”€ friends.ts # Friend requests, search, management β”‚ β”‚ β”‚ β”œβ”€β”€ repeatProfiles.ts# Repeat profile CRUD β”‚ β”‚ β”‚ └── pushNotifications.ts β”‚ β”‚ β”œβ”€β”€ middleware/ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.ts # JWT verification β”‚ β”‚ β”‚ β”œβ”€β”€ errorHandler.ts β”‚ β”‚ β”‚ └── validation.ts # Zod validation middleware β”‚ β”‚ β”œβ”€β”€ services/ β”‚ β”‚ └── utils/ β”‚ β”œβ”€β”€ drizzle.config.ts β”‚ └── Dockerfile β”œβ”€β”€ electron/ # Desktop app entry β”œβ”€β”€ android/ # Native Android project β”œβ”€β”€ assets/ # Images, fonts β”œβ”€β”€ patches/ # patch-package fixes └── plugins/ # Expo config plugins ``` --- ## Data Models ### Task ```typescript { id: string; title: string; description: string; categoryId: string; priority: 'none' | 'low' | 'medium' | 'high' | 'critical'; completed: boolean; dueDate: number; // timestamp (ms) dueTime: string; // "HH:MM" (24h stored, 12h displayed) allDay: boolean; assigneeId: string | null; repeatProfileId: string | null; seriesId: string | null; // For repeating tasks isTemplate: boolean; // Series template reminderOffset: string | null; // e.g., "5m", "1h", "1d" createdAt: Date; updatedAt: Date; subtasks: Subtask[]; } ``` ### Category ```typescript { id: string; name: string; color: '#HEX'; order: number; createdAt: Date; updatedAt: Date; } ``` ### Subtask ```typescript { id: string; taskId: string; parentSubtaskId: string | null; // For nesting title: string; completed: boolean; order: number; assigneeId: string | null; createdAt: Date; updatedAt: Date; } ``` ### Repeat Profile ```typescript { id: string; name: string; frequency: 'daily' | 'weekly' | 'monthly' | 'yearly' | 'custom'; interval: number; daysOfWeek: number[]; // 0-6 for weekly dayOfMonth: number | null; // For monthly monthOfYear: number | null; // For yearly endDate: number | null; // Timestamp occurrences: number | null; createdAt: Date; updatedAt: Date; } ``` ### Friendship ```typescript { id: string; userId: string; // Requester friendId: string; // Recipient status: 'pending' | 'accepted' | 'declined' | 'blocked'; createdAt: Date; updatedAt: Date; } ``` --- ## Default Categories | Name | Color | Order | |------|-------|-------| | Work | #E53935 (Red) | 0 | | Personal | #43A047 (Green) | 1 | | School | #1E88E5 (Blue) | 2 | | Shopping | #FB8C00 (Orange) | 3 | | Health | #8E24AA (Purple) | 4 | | Finance | #FDD835 (Yellow) | 5 | --- ## Priority Colors | Priority | Color | |----------|-------| | None | #9E9E9E | | Low | #43A047 | | Medium | #FB8C00 | | High | #E53935 | | Critical | #B71C1C | --- ## Getting Started ### Prerequisites - Node.js 20+ - npm or yarn - Expo CLI (`npm install -g expo-cli`) - iOS Simulator (Mac) / Android Studio for mobile testing - PostgreSQL 16+ (or Docker) ### Installation ```bash cd carry-your-live npm install cd ../backend npm install ``` ### Development #### Frontend ```bash cd carry-your-live # Start Expo dev server npx expo start # Run on specific platform npx expo start --ios npx expo start --android npx expo start --web ``` #### Backend ```bash cd backend # Start PostgreSQL (Docker) docker-compose up -d postgres # Configure environment cp .env.example .env # Edit .env with your settings # Run migrations npm run db:push # Start dev server npm run dev ``` Server runs at `http://localhost:3000` (health check: `GET /health`) #### Desktop (Electron) ```bash cd carry-your-live # Development with live reload npm run desktop:dev # Production build npm run desktop:dist ``` ### Building #### EAS Build (cloud) ```bash # Install EAS CLI npm install -g eas-cli # Configure project eas build:configure # Build for platforms eas build --platform ios eas build --platform android eas build --platform web ``` Profiles defined in `eas.json` (`development`, `preview`, `production`; production auto-increments version code). #### Gradle (local Android APK) ```bash cd carry-your-live/android # Debug APK (unsigned) ./gradlew assembleDebug # Release APK (signed with debug keystore) ./gradlew assembleRelease ``` Output: ``` android/app/build/outputs/apk/debug/app-debug.apk android/app/build/outputs/apk/release/app-release.apk ``` --- ## CI/CD Pipeline (Gitea Actions) `.gitea/workflows/build-apk.yml` builds a release APK on every push to `main` (also manually triggerable via `workflow_dispatch`): 1. **Checkout** and setup Node 22, JDK 17 (Temurin) 2. **Android SDK**: installs cmdline-tools, licenses, platform-tools, `platforms;android-35`, `build-tools;35.0.0`, `ndk;27.1.12297006` 3. **JS deps**: `npm ci` in `carry-your-live/` 4. **Debug keystore**: generates `carry-your-live/android/app/debug.keystore` with `keytool` 5. **Build**: `./gradlew assembleRelease` in `carry-your-live/android/` 6. **Upload**: APK saved as `carry-your-live-release` artifact To run locally exactly as CI does: ```bash keytool -genkeypair -v \ -keystore carry-your-live/android/app/debug.keystore \ -alias androiddebugkey -storepass android -keypass android \ -keyalg RSA -keysize 2048 -validity 10000 \ -dname "CN=Android Debug,O=Android,C=US" cd carry-your-live/android && ./gradlew assembleRelease ``` --- ## Backend API Specification Server runs at `http://localhost:3000/api` (configurable in `src/services/api.ts` and `src/database/sync.ts`): ### Authentication - `POST /api/auth/register` - Register new user - `POST /api/auth/login` - Login (returns access + refresh tokens) - `POST /api/auth/refresh` - Refresh access token - `POST /api/auth/forgot-password` - Request password reset - `POST /api/auth/reset-password` - Reset password with token - `GET /api/auth/me` - Get current user ### Categories - `GET /api/categories` - List categories - `POST /api/categories` - Create category - `PATCH /api/categories/:id` - Update category - `DELETE /api/categories/:id` - Delete category ### Tasks - `GET /api/tasks` - List tasks (with filters: category, completed, due date range, assignee) - `GET /api/tasks/:id` - Get task with subtasks - `POST /api/tasks` - Create task - `PATCH /api/tasks/:id` - Update task - `DELETE /api/tasks/:id` - Delete task (scopes: this/future/all for repeating) - `POST /api/tasks/batch` - Batch operations ### Subtasks - `GET /api/subtasks/task/:taskId` - List subtasks for task - `POST /api/subtasks/task/:taskId` - Create subtask - `PATCH /api/subtasks/:id` - Update subtask - `DELETE /api/subtasks/:id` - Delete subtask ### Repeat Profiles - `GET /api/repeat-profiles` - List repeat profiles - `POST /api/repeat-profiles` - Create repeat profile - `PATCH /api/repeat-profiles/:id` - Update repeat profile - `DELETE /api/repeat-profiles/:id` - Delete repeat profile ### Users - `GET /api/users/me` - Get user with settings - `PATCH /api/users/me/settings` - Update settings (darkMode, defaultCategoryId, sortOrder, etc.) - `GET /api/users/search` - Search users (for friends) ### Friends - `GET /api/friends` - List accepted friends - `GET /api/friends/requests` - List pending requests (incoming/outgoing) - `POST /api/friends/request` - Send friend request - `PATCH /api/friends/request/:id/accept` - Accept request - `PATCH /api/friends/request/:id/decline` - Decline request - `DELETE /api/friends/:id` - Remove friend ### Sync (Offline-first) - `GET /api/sync?since=` - Pull changes since timestamp - `POST /api/sync/push` - Push local changes --- ## Sync Protocol The sync endpoint uses a cursor-based approach with tombstones: 1. **Pull**: Client sends `since` timestamp, server returns all changes since then ```json { "categories": [...], "tasks": [...], "subtasks": [...], "repeatProfiles": [...], "friendships": [...], "tombstones": [...], "timestamp": 1234567890 } ``` 2. **Push**: Client sends batched changes with `lastPulledAt` ```json { "changes": { "categories": [...], "tasks": [...], "subtasks": [...], "repeatProfiles": [...], "friendships": [...] }, "tombstones": [...], "lastPulledAt": 1234567890 } ``` 3. **Conflict Resolution**: Last-write-wins based on `updatedAt` (customizable in `src/database/sync.ts`) --- ## Configuration ### Frontend Environment Variables Create `.env` file in `carry-your-live/`: ``` EXPO_PUBLIC_API_URL=http://your-api-url/api ``` ### Backend Environment Variables Create `.env` file in `backend/`: ``` DATABASE_URL=postgresql://user:pass@localhost:5432/carry_your_live JWT_SECRET=your-32-char-secret PORT=3000 NODE_ENV=development FRONTEND_URL=http://localhost:8081 ``` ### App Config Modify `app.json` for: - App name, slug, version - Icon, splash screen - Permissions (notifications, etc.) - Orientation, theme --- ## Visual Style Guide - **Background**: White (#FFFFFF) / Dark mode (planned) - **Primary Accent**: #E53935 (Pink/Red) - customizable - **Typography**: Black (#212121) primary, #757575 secondary, #9E9E9E tertiary - **Borders**: Thin (#E0E0E0), selected #E53935 - **Radius**: 16-20px for cards/buttons/inputs - **Spacing**: 8px grid system - **Shadows**: Minimal (elevation 1-3) - **Animations**: 150-250ms, cubic easing --- ## Offline-First Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Expo App │────▢│ WatermelonDB │────▢│ Backend β”‚ β”‚ (iOS/Androidβ”‚ β”‚ (SQLite) β”‚ β”‚ (Postgres) β”‚ β”‚ Web) │◀───▢│ + Sync │◀───▢│ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` 1. All writes go to local SQLite first 2. Reactive queries update UI instantly 3. Background sync pushes/pulls changes 4. Conflict resolution: last-write-wins (customizable) 5. Tombstones track deletions for sync --- ## Current Implementation Status Based on code audit (August 2026): | Feature | Status | Notes | |---------|--------|-------| | Core CRUD (tasks, subtasks, categories) | βœ… Complete | | | Nested subtasks | βœ… Complete | Unlimited depth | | Repeating tasks | βœ… Complete | Profiles, series, this/future/all delete | | Categories & priorities | βœ… Complete | | | Calendar with date strip | βœ… Complete | Month nav, day detail | | Stats screen | βœ… Complete | Client-side only | | Settings screen | βœ… Complete | Most settings wired | | Friends system | βœ… Complete | Backend + UI | | Task assignees | βœ… Complete | Schema v7, UI, sync | | QuickAddBar | βœ… Complete | Tasks + Calendar | | Offline sync (WatermelonDB) | βœ… Complete | Schema v21, tombstones | | Backend API | βœ… Complete | Express + Drizzle + Postgres | | Auth (JWT) | βœ… Complete | Register, login, refresh, forgot/reset | | Dark mode / theme toggle | ❌ Missing | Backend column exists, UI not implemented | | Notifications toggle | 🟑 Partial | Stored but not respected | | Global reminder preference | 🟑 Partial | Stored but not applied | | Forgot/reset password UI | 🟑 Partial | Backend done, no client UI | | Pull-to-refresh β†’ sync | 🟑 Partial | Reloads local only | | Client settings sync | 🟑 Partial | AsyncStorage only, not synced to backend | | Reminder enum mismatch | 🟑 Partial | Client uses '5m'/'1h', spec uses minutes | --- ## Roadmap Highlights ### v1.1.0 β€” Friends & Assignees (Current Unreleased) - Ship existing Unreleased changes - Fix notifications toggle, wire up `rescheduleAllReminders()` - Apply global reminder preference - Make pull-to-refresh trigger real sync - Add forgot/reset password UI - Unify reminder offset enums ### v1.2.0 β€” Theming & Findability - Light mode + follow-system-theme - Sync all settings to `PATCH /users/me/settings` - Task search (filter + global) - Friend request badges/indicators ### v1.3.0 β€” Stats & Insights - Persisted stats snapshots - Productivity trends, streaks - Export stats (CSV/image) ### v1.4.0 β€” Quick Capture & Calendar UX - Natural language quick-add - Drag-and-drop rescheduling in calendar - Month grid view - "Today at a glance" dashboard ### v1.5.0 β€” Power Tools & Personalization - Task templates, soft-archive, attachments - Markdown support, deep links - Biometric lock, haptics, reduced motion - Android home-screen widget ### v2.0.0 β€” Collaboration - Real task assignment delivery - Shared lists with permissions - Server push notifications (FCM/APNs) - Comments/activity feed --- ## Contributing 1. Follow existing code conventions 2. Use TypeScript strict mode 3. Write components with React Hook Form + Zod 4. Use WatermelonDB decorators for models 5. Test offline scenarios 6. Run `npm run lint` and `npm run typecheck` before committing --- ## License MIT