Explore the 96Blocks-iOS app at /Users/neog/Apps/iOS/96Blocks-iOS to identify missing features and incomplete implementations.

Check for:
1. TODO comments or incomplete code
2. Features mentioned in CLAUDE.md as "Future" or "Phase 2+"
3. Empty or stub implementations
4. Missing tests
5. Missing localization
6. Missing export/import functionality
7. Missing integrations (Calendar, Reminders, Shortcuts)
8. Missing offline support patterns
9. Missing onboarding completion
10. Settings that aren't fully implemented

Report specific file paths and areas that need implementation.


I'll explore the 96Blocks-iOS app to identify missing features and incomplete implementations. Let me start by examining the project structure and key files.


Bash

find /Users/neog/Apps/iOS/96Blocks-iOS -type f -name "*.md" | head -20

Find markdown documentation files in 96Blocks-iOS


Error: EISDIR: illegal operation on a directory, read


Let me read the CLAUDE.md file and explore the project structure.


ls -la /Users/neog/Apps/iOS/96Blocks-iOS/ | head -30

List directory contents of 96Blocks-iOS


find /Users/neog/Apps/iOS/96Blocks-iOS -type f \( -name "*.swift" -o -name "*.json" \) | head -30

Find Swift and JSON files in 96Blocks-iOS


     1→# CLAUDE.md - 96Blocks-iOS
     2→
     3→## Project Overview
     4→
     5→**96Blocks-iOS** is a B2B SaaS iOS application for day planning with ROI tracking. The core concept divides each day into 96 blocks of 15 minutes each, allowing users to plan, track, and measure the monetary value of their time.
     6→
     7→### Key Features
     8→
     9→- **96-Block Timeline**: Vertical timeline showing all 96 blocks of the day
    10→- **ROI Tracking**: Estimated and actual monetary value (R$) per block
    11→- **Task Backlog**: Task management with priority, category, and time estimates
    12→- **Goals**: High-level objectives with progress tracking
    13→- **Templates**: Pre-defined day schedules (Workday, Weekend, Focus Day)
    14→- **Analytics**: Productivity score, ROI efficiency, category breakdown
    15→
    16→## Tech Stack
    17→
    18→- **UI**: SwiftUI (iOS 17+)
    19→- **Data**: SwiftData
    20→- **Architecture**: MVVM with @MainActor
    21→- **Platforms**: iPhone, iPad, Mac Catalyst
    22→- **Dependencies**: None (pure Apple frameworks)
    23→
    24→## Project Structure
    25→
    26→```
    27→96Blocks-iOS/
    28→├── App/
    29→│   ├── 96BlocksApp.swift         # @main entry point
    30→│   └── MainTabView.swift         # Adaptive navigation
    31→├── Models/
    32→│   ├── Block.swift               # 15-min block model
    33→│   ├── Task.swift                # Backlog task model
    34→│   ├── Goal.swift                # Goal tracking
    35→│   ├── Template.swift            # Day templates
    36→│   └── DailySummary.swift        # Analytics summary
    37→├── Services/
    38→│   └── DataManager.swift         # SwiftData manager
    39→├── Views/
    40→│   ├── DayPlanner/
    41→│   │   ├── DayPlannerView.swift  # Main timeline view
    42→│   │   └── BlockRow.swift        # Individual block cell
    43→│   ├── Backlog/
    44→│   │   └── BacklogView.swift     # Task management
    45→│   ├── Analytics/
    46→│   │   └── AnalyticsView.swift   # ROI dashboard
    47→│   └── Settings/
    48→│       └── SettingsView.swift    # Configuration
    49→├── Components/
    50→│   └── HapticManager.swift       # Haptic feedback
    51→└── Extensions/
    52→```
    53→
    54→## Data Models
    55→
    56→### Block (Core)
    57→- `blockIndex`: 0-95 (00:00 to 23:45)
    58→- `title`: Task description
    59→- `category`: work, personal, health, learning, meeting, focus, break, sleep
    60→- `estimatedValueBRL`: Expected ROI in R$
    61→- `actualValueBRL`: Real ROI achieved
    62→- `status`: planned, inProgress, completed, skipped
    63→
    64→### Task96 (Backlog)
    65→- `priority`: low, medium, high, urgent
    66→- `estimatedBlocks`: Number of 15-min blocks needed
    67→- `estimatedValueBRL`: Expected value
    68→- `goalId`: Link to parent goal
    69→
    70→### Goal
    71→- `targetValueBRL`: Target monetary value
    72→- `timeframe`: weekly, monthly, quarterly, yearly
    73→- `valueGeneratedBRL`: Progress tracking
    74→
    75→## Quick Commands
    76→
    77→```bash
    78→# Generate Xcode project
    79→cd ~/Apps/iOS/96Blocks-iOS
    80→ruby generate-xcode-project.rb
    81→
    82→# Open project
    83→open 96Blocks-iOS.xcodeproj
    84→
    85→# Build for simulator
    86→xcodebuild -project 96Blocks-iOS.xcodeproj \
    87→  -scheme 96Blocks-iOS \
    88→  -sdk iphonesimulator \
    89→  -destination 'platform=iOS Simulator,name=iPhone 17 Pro'
    90→```
    91→
    92→## Key Patterns
    93→
    94→### DataManager (Singleton)
    95→```swift
    96→@MainActor
    97→class DataManager: ObservableObject {
    98→    static let shared = DataManager()
    99→    let modelContainer: ModelContainer
   100→
   101→    func getBlocks(for date: Date) -> [Block]
   102→    func getTodayROI() -> (estimated: Decimal, actual: Decimal)
   103→    func getProductivityScore() -> Int
   104→}
   105→```
   106→
   107→### Block Time Calculation
   108→```swift
   109→// Block index to time
   110→let hour = blockIndex / 4        // 0-23
   111→let minute = (blockIndex % 4) * 15  // 0, 15, 30, 45
   112→
   113→// Current block
   114→let currentIndex = hour * 4 + minute / 15
   115→```
   116→
   117→### ROI Calculation
   118→```swift
   119→let efficiency = actual / estimated * 100  // Percentage
   120→let score = (completionRate * 0.4) + (roiEfficiency * 0.4) + (taskScore * 0.2)
   121→```
   122→
   123→## Future Enhancements (Phase 2+)
   124→
   125→1. **AI Integration**: Claude API for automatic day planning
   126→2. **Backend API**: FastAPI for multi-tenant B2B
   127→3. **Team Features**: Dashboard admin, team analytics
   128→4. **Web Dashboard**: Next.js for desktop access
   129→5. **Notifications**: Block reminders, daily summary
   130→6. **Widgets**: Home screen productivity widget
   131→
   132→## Related Documentation
   133→
   134→- **Business Plan**: `~/.claude/plans/buzzing-painting-hoare.md`
   135→- **ProductivityHub Reference**: `~/Apps/iOS/ProductivityHub-iOS/CLAUDE.md`
   136→- **MeusFIIs AI Pattern**: `~/Apps/iOS/MeusFIIs-iOS/Services/AI/`
   137→
   138→---
   139→
   140→**Created**: 2025-12-08
   141→**Version**: 1.0.0 (MVP)
   142→**Status**: Ready for Development
   143→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

# CLAUDE.md - 96Blocks-iOS

## Project Overview

**96Blocks-iOS** is a B2B SaaS iOS application for day planning with ROI tracking. The core concept divides each day into 96 blocks of 15 minutes each, allowing users to plan, track, and measure the monetary value of their time.

### Key Features

- **96-Block Timeline**: Vertical timeline showing all 96 blocks of the day
- **ROI Tracking**: Estimated and actual monetary value (R$) per block
- **Task Backlog**: Task management with priority, category, and time estimates
- **Goals**: High-level objectives with progress tracking
- **Templates**: Pre-defined day schedules (Workday, Weekend, Focus Day)
- **Analytics**: Productivity score, ROI efficiency, category breakdown

## Tech Stack

- **UI**: SwiftUI (iOS 17+)
- **Data**: SwiftData
- **Architecture**: MVVM with @MainActor
- **Platforms**: iPhone, iPad, Mac Catalyst
- **Dependencies**: None (pure Apple frameworks)

## Project Structure

```
96Blocks-iOS/
├── App/
│   ├── 96BlocksApp.swift         # @main entry point
│   └── MainTabView.swift         # Adaptive navigation
├── Models/
│   ├── Block.swift               # 15-min block model
│   ├── Task.swift                # Backlog task model
│   ├── Goal.swift                # Goal tracking
│   ├── Template.swift            # Day templates
│   └── DailySummary.swift        # Analytics summary
├── Services/
│   └── DataManager.swift         # SwiftData manager
├── Views/
│   ├── DayPlanner/
│   │   ├── DayPlannerView.swift  # Main timeline view
│   │   └── BlockRow.swift        # Individual block cell
│   ├── Backlog/
│   │   └── BacklogView.swift     # Task management
│   ├── Analytics/
│   │   └── AnalyticsView.swift   # ROI dashboard
│   └── Settings/
│       └── SettingsView.swift    # Configuration
├── Components/
│   └── HapticManager.swift       # Haptic feedback
└── Extensions/
```

## Data Models

### Block (Core)
- `blockIndex`: 0-95 (00:00 to 23:45)
- `title`: Task description
- `category`: work, personal, health, learning, meeting, focus, break, sleep
- `estimatedValueBRL`: Expected ROI in R$
- `actualValueBRL`: Real ROI achieved
- `status`: planned, inProgress, completed, skipped

### Task96 (Backlog)
- `priority`: low, medium, high, urgent
- `estimatedBlocks`: Number of 15-min blocks needed
- `estimatedValueBRL`: Expected value
- `goalId`: Link to parent goal

### Goal
- `targetValueBRL`: Target monetary value
- `timeframe`: weekly, monthly, quarterly, yearly
- `valueGeneratedBRL`: Progress tracking

## Quick Commands

```bash
# Generate Xcode project
cd ~/Apps/iOS/96Blocks-iOS
ruby generate-xcode-project.rb

# Open project
open 96Blocks-iOS.xcodeproj

# Build for simulator
xcodebuild -project 96Blocks-iOS.xcodeproj \
  -scheme 96Blocks-iOS \
  -sdk iphonesimulator \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro'
```

## Key Patterns

### DataManager (Singleton)
```swift
@MainActor
class DataManager: ObservableObject {
    static let shared = DataManager()
    let modelContainer: ModelContainer

    func getBlocks(for date: Date) -> [Block]
    func getTodayROI() -> (estimated: Decimal, actual: Decimal)
    func getProductivityScore() -> Int
}
```

### Block Time Calculation
```swift
// Block index to time
let hour = blockIndex / 4        // 0-23
let minute = (blockIndex % 4) * 15  // 0, 15, 30, 45

// Current block
let currentIndex = hour * 4 + minute / 15
```

### ROI Calculation
```swift
let efficiency = actual / estimated * 100  // Percentage
let score = (completionRate * 0.4) + (roiEfficiency * 0.4) + (taskScore * 0.2)
```

## Future Enhancements (Phase 2+)

1. **AI Integration**: Claude API for automatic day planning
2. **Backend API**: FastAPI for multi-tenant B2B
3. **Team Features**: Dashboard admin, team analytics
4. **Web Dashboard**: Next.js for desktop access
5. **Notifications**: Block reminders, daily summary
6. **Widgets**: Home screen productivity widget

## Related Documentation

- **Business Plan**: `~/.claude/plans/buzzing-painting-hoare.md`
- **ProductivityHub Reference**: `~/Apps/iOS/ProductivityHub-iOS/CLAUDE.md`
- **MeusFIIs AI Pattern**: `~/Apps/iOS/MeusFIIs-iOS/Services/AI/`

---

**Created**: 2025-12-08
**Version**: 1.0.0 (MVP)
**Status**: Ready for Development


total 120
drwxr-xr-x@ 16 neog  staff    512 Dec 15 19:02 .
drwxr-xr-x@ 34 neog  staff   1088 Dec 18 12:31 ..
-rw-r--r--@  1 neog  staff   6148 Dec 15 19:02 .DS_Store
-rw-r--r--   1 neog  staff    770 Dec  8 22:15 96Blocks-iOS.entitlements
drwxr-xr-x@  6 neog  staff    192 Dec  8 22:14 96Blocks-iOS.xcodeproj
drwxr-xr-x@  4 neog  staff    128 Dec 10 14:45 App
-rw-------@  1 neog  staff   4427 Dec  8 18:35 CLAUDE.md
drwxr-xr-x@  4 neog  staff    128 Dec  8 20:34 Components
drwxr-xr-x@  2 neog  staff     64 Dec  8 18:28 Extensions
-rw-r--r--@  1 neog  staff    789 Dec  8 22:03 Info.plist
drwxr-xr-x@  8 neog  staff    256 Dec 10 14:56 Models
drwxr-xr-x@ 11 neog  staff    352 Dec 10 14:56 Services
drwxr-xr-x@  7 neog  staff    224 Dec  8 20:06 Views
-rw-r--r--@  1 neog  staff  15298 Dec  8 21:18 gen_project.rb
-rw-------@  1 neog  staff  13538 Dec  8 18:35 generate-xcode-project.rb
-rw-------@  1 neog  staff   1545 Dec  8 22:03 project.yml


Now let me search for TODO comments, FIXME notes, and other indicators of incomplete implementations across the codebase.


Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:10:// MARK: - Validation Error Code
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:40:// MARK: - Validation Error
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:60:// MARK: - Validation Result
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:93:    // MARK: - Combinators
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:126:// MARK: - Validation Builder
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:235:// MARK: - Extensions
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:63:    // MARK: - Productivity Score Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:123:    // MARK: - Day Flow Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:259:    // MARK: - Weekly Heatmap Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:414:    // MARK: - ROI Summary Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:473:    // MARK: - Blocks Summary Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:533:    // MARK: - Category Breakdown Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:580:    // MARK: - Recent Activity Card
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:629:    // MARK: - Helpers
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:651:// MARK: - Analytics Period
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:12:    // MARK: - Constants
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:20:    // MARK: - Main Validation
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:67:    // MARK: - Quick Validations
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:91:    // MARK: - Batch Validation
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:101:    // MARK: - Helper Methods
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:115:    // MARK: - Logging Integration
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:11:// MARK: - Issue Type
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:62:// MARK: - Severity
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:85:// MARK: - Integrity Issue
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:108:// MARK: - Integrity Report
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:141:// MARK: - Integrity Service
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:147:    // MARK: - Published Properties
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:153:    // MARK: - Private Properties
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:157:    // MARK: - Initialization
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:163:    // MARK: - Main Check
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:270:    // MARK: - Individual Checks
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:451:    // MARK: - Auto Fix
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:570:    // MARK: - Fix All
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:12:    // MARK: - Constants
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:22:    // MARK: - Main Validation
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:84:    // MARK: - Quick Validations
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:119:    // MARK: - Batch Validation
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:129:    // MARK: - Helper Methods
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:147:    // MARK: - Logging Integration
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:11:// MARK: - Log Level
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:14:    case debug = "DEBUG"
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:41:// MARK: - Log Category
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:71:// MARK: - Log Entry
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:105:// MARK: - Logging Service
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:111:    // MARK: - Published Properties
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:117:    // MARK: - Private Properties
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:126:    // MARK: - Initialization
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:139:    // MARK: - Main Logging Method
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:190:        #if DEBUG
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:202:    // MARK: - Convenience Methods
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:229:    // MARK: - Query Methods
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:260:    // MARK: - Export
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:278:// MARK: - Global Convenience Functions
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:44:    // MARK: - Health Tab
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:115:    // MARK: - Logs Tab
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:190:    // MARK: - Metrics Tab
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:237:    // MARK: - Status Row
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:279:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:302:    // MARK: - Actions
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:324:// MARK: - Issue Row
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:380:// MARK: - Log Row
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:414:// MARK: - Metric Row
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:438:// MARK: - Data Explorer View
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:505:// MARK: - Preview
Apps/iOS/96Blocks-iOS/Services/AIService.swift:13:// MARK: - Secure API Key Storage
Apps/iOS/96Blocks-iOS/Services/AIService.swift:69:// MARK: - AI Provider Enum
Apps/iOS/96Blocks-iOS/Services/AIService.swift:132:// MARK: - AI Service
Apps/iOS/96Blocks-iOS/Services/AIService.swift:138:    // MARK: - Published Properties
Apps/iOS/96Blocks-iOS/Services/AIService.swift:145:    // MARK: - Configuration
Apps/iOS/96Blocks-iOS/Services/AIService.swift:162:    // MARK: - API Key Management (Secure Keychain Storage)
Apps/iOS/96Blocks-iOS/Services/AIService.swift:213:    // MARK: - Legacy API Key Methods (for backward compatibility)
Apps/iOS/96Blocks-iOS/Services/AIService.swift:237:    // MARK: - Generate Day Plan
Apps/iOS/96Blocks-iOS/Services/AIService.swift:265:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AIService.swift:276:                #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AIService.swift:282:                #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AIService.swift:308:    // MARK: - Provider-Specific Generation
Apps/iOS/96Blocks-iOS/Services/AIService.swift:317:        #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AIService.swift:334:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AIService.swift:344:    // MARK: - Build Request
Apps/iOS/96Blocks-iOS/Services/AIService.swift:390:    // MARK: - Parse Response
Apps/iOS/96Blocks-iOS/Services/AIService.swift:424:    // MARK: - Build Prompt
Apps/iOS/96Blocks-iOS/Services/AIService.swift:490:    // MARK: - Parse Generated Blocks
Apps/iOS/96Blocks-iOS/Services/AIService.swift:525:    // MARK: - Apply Generated Plan
Apps/iOS/96Blocks-iOS/Services/AIService.swift:542:// MARK: - Request/Response Models
Apps/iOS/96Blocks-iOS/Services/AIService.swift:623:// MARK: - Errors
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:12:    // MARK: - Constants
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:19:    // MARK: - Main Validation
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:110:    // MARK: - Quick Validations
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:187:    // MARK: - Batch Validation
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:197:    // MARK: - Helper Methods
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:206:    // MARK: - Logging Integration
Apps/iOS/96Blocks-iOS/App/MainTabView.swift:55:    // MARK: - Tab View (iPhone)
Apps/iOS/96Blocks-iOS/App/MainTabView.swift:85:    // MARK: - Sidebar Navigation (iPad/Mac)
Apps/iOS/96Blocks-iOS/App/MainTabView.swift:119:// MARK: - Navigation Items
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:20:    // MARK: - CloudKit Configuration
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:23:    // MARK: - Model Container
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:26:    // MARK: - Published Properties for UI Binding
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:34:    // MARK: - Selected Date
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:37:    // MARK: - Loading State
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:40:    // MARK: - Sync State
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:50:    // MARK: - Initialization
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:85:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:95:    // MARK: - CloudKit Sync Monitoring
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:118:        #if DEBUG
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:141:    // MARK: - Directory Setup
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:162:    // MARK: - Context
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:167:    // MARK: - Load All Data
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:189:    // MARK: - Block Operations
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:275:    // MARK: - Task Operations
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:316:    // MARK: - Goal Operations
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:351:    // MARK: - Template Operations
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:412:    // MARK: - Daily Summary Operations
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:442:    // MARK: - BlockStep Operations
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:566:    // MARK: - Statistics
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:608:    // MARK: - Save Context
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:618:    // MARK: - Sample Data
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:685:    // MARK: - Clear All Data (for testing)
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:17:    // MARK: - Published Properties
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:25:    // MARK: - Step Mode Properties
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:33:    // MARK: - Timer Configuration
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:36:    // MARK: - Private Properties
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:48:    // MARK: - Initialization
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:57:    // MARK: - Timer Control
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:205:    // MARK: - Step Navigation
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:281:    // MARK: - Timer Loop
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:360:    // MARK: - State Persistence
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:416:    // MARK: - App Lifecycle
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:449:    // MARK: - Notifications
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:479:    // MARK: - Step Notifications
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:509:    // MARK: - Formatted Time
Apps/iOS/96Blocks-iOS/Models/Task.swift:97:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Models/Task.swift:131:// MARK: - Task Priority
Apps/iOS/96Blocks-iOS/Models/Task.swift:166:// MARK: - Task Status
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:12:    // MARK: - Configuration
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:15:    // MARK: - Keys
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:23:    // MARK: - Save
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:45:    // MARK: - Get
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:67:    // MARK: - Delete
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:80:    // MARK: - Exists
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:93:    // MARK: - Update
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:119:    // MARK: - Clear All
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:21:    // MARK: - Authorization
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:46:    // MARK: - Block Reminders
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:52:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:100:    // MARK: - Daily Summary
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:105:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:139:    // MARK: - Morning Planning Reminder
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:144:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:178:    // MARK: - ROI Milestone
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:183:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:211:    // MARK: - Clear All
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:223:    // MARK: - Schedule Day Reminders
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:238:// MARK: - Notification Actions
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:297:// MARK: - Notification Delegate
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:350:    // MARK: - Action Handlers
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:409:// MARK: - Navigation Notifications
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:12:// MARK: - App Notifications for Menu Commands
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:89:    // MARK: - Scene Phase Handling
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:106:    // MARK: - Setup
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:114:                #if DEBUG
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:218:    // MARK: - Account Section
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:360:// MARK: - Goals List View
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:422:// MARK: - Goal Edit Sheet
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:492:// MARK: - Templates List View
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:526:// MARK: - Custom API Key Sheet
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:610:// MARK: - Export Sheet
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:970:// MARK: - Share Sheet
Apps/iOS/96Blocks-iOS/Models/Goal.swift:55:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Models/Goal.swift:89:// MARK: - Goal Timeframe
Apps/iOS/96Blocks-iOS/Models/Goal.swift:116:// MARK: - Goal Status
Apps/iOS/96Blocks-iOS/Components/AppTheme.swift:10:// MARK: - Color Extension (Hex Support)
Apps/iOS/96Blocks-iOS/Components/AppTheme.swift:27:// MARK: - App Colors
Apps/iOS/96Blocks-iOS/Components/AppTheme.swift:53:// MARK: - Environment Key
Apps/iOS/96Blocks-iOS/Components/AppTheme.swift:65:// MARK: - View Modifier for Theme
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:16:    // MARK: - Published Properties
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:25:    // MARK: - UserDefaults Keys
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:30:    // MARK: - Initialization
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:37:    // MARK: - Load Stored Credentials
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:51:    // MARK: - Verify Credentials
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:62:                    #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:68:                    #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:74:                    #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:82:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:88:    // MARK: - Check iCloud Status
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:95:                    #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:100:                #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:107:    // MARK: - Sign In With Apple
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:120:    // MARK: - Sign Out
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:133:        #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:138:    // MARK: - Save Credentials
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:153:        #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:158:    // MARK: - Display Name
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:169:    // MARK: - iCloud Available
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:175:// MARK: - ASAuthorizationControllerDelegate
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:204:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:233:            #if DEBUG
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:240:// MARK: - CKAccountStatus Extension
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:85:    // MARK: - Header View
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:134:    // MARK: - Day Progress Bar
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:205:    // MARK: - ROI Summary
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:344:    // MARK: - Timeline View
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:378:    // MARK: - Helper Methods
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:428:// MARK: - Date Picker Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:456:// MARK: - Template Selection Sheet
Apps/iOS/96Blocks-iOS/Models/Block.swift:80:        #if DEBUG
Apps/iOS/96Blocks-iOS/Models/Block.swift:87:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Models/Block.swift:157:// MARK: - Block Category
Apps/iOS/96Blocks-iOS/Models/Block.swift:223:// MARK: - Block Status
Apps/iOS/96Blocks-iOS/Models/Block.swift:240:// MARK: - Block Extensions
Apps/iOS/96Blocks-iOS/Models/BlockStep.swift:39:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Models/BlockStep.swift:76:// MARK: - Step Templates
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:10:// MARK: - Step List View (Container)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:127:// MARK: - Step Row View
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:191:// MARK: - Add Step Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:305:// MARK: - Step Template Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:377:// MARK: - Compact Step Progress Badge
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:404:// MARK: - Preview
Apps/iOS/96Blocks-iOS/Models/DailySummary.swift:48:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Models/DailySummary.swift:93:// MARK: - DailySummary Builder
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:126:    // MARK: - Time Column
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:144:    // MARK: - Status Indicator
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:175:    // MARK: - Content Column
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:206:    // MARK: - ROI Badge
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:227:    // MARK: - Background
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:245:    // MARK: - Helpers
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:256:// MARK: - Block Edit Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/BlockRow.swift:315:                // MARK: - Steps Section
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:13:    // MARK: - User Preference
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:48:    // MARK: - Prepared Generators (for better performance)
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:59:    // MARK: - Preparation (call on app launch or before expected use)
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:79:    // MARK: - Impact Feedback
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:107:    // MARK: - Notification Feedback
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:116:    // MARK: - Selection Feedback
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:125:    // MARK: - Convenience Methods for 96Blocks
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:82:// MARK: - Welcome Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:142:// MARK: - Concept Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:189:// MARK: - ROI Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:241:// MARK: - Setup Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:318:// MARK: - Permissions Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:401:// MARK: - API Key Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:491:// MARK: - Complete Page
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:551:// MARK: - Helper Views
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:573:// MARK: - Preview
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:77:    // MARK: - Normal Mode Timer
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:108:    // MARK: - Step Mode Timer
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:194:    // MARK: - Normal Mode Controls
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:239:    // MARK: - Step Mode Controls
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:307:// MARK: - Complete Block Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:407:// MARK: - Mini Timer (for toolbar/floating)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:459:// MARK: - Timer Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:152:    // MARK: - Provider Selector
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:203:    // MARK: - Stats Preview
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:258:    // MARK: - Generate Plan
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:291:    // MARK: - Apply Plan
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:312:// MARK: - API Key Sheet
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:495:// MARK: - Generated Plan Preview
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:587:// MARK: - Generated Block Row
Apps/iOS/96Blocks-iOS/Models/Template.swift:92:    // MARK: - Computed Properties
Apps/iOS/96Blocks-iOS/Models/Template.swift:126:// MARK: - Template Type
Apps/iOS/96Blocks-iOS/Models/Template.swift:147:// MARK: - Template Block
Apps/iOS/96Blocks-iOS/Models/Template.swift:176:// MARK: - System Templates
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:70:    // MARK: - Empty State
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:86:    // MARK: - Task List
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:146:    // MARK: - Filter Menu
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:214:    // MARK: - Helpers
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:252:// MARK: - Task Row
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:337:// MARK: - Task Edit Sheet


Apps/iOS/96Blocks-iOS/Services/AIService.swift:246:        error = nil
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:41:        let status = SecItemAdd(query as CFDictionary, nil)
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:61:            return nil
Apps/iOS/96Blocks-iOS/Services/KeychainService.swift:89:        let status = SecItemCopyMatching(query as CFDictionary, nil)
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:78:        return nil
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:145:    func validateNotEmpty(_ keyPath: KeyPath<T, String>, field: String, message: String? = nil) -> ValidationBuilder<T> {
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:158:    func validateRange<V: Comparable>(_ keyPath: KeyPath<T, V>, field: String, min: V, max: V, message: String? = nil) -> ValidationBuilder<T> {
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:171:    func validateNonNegative<V: Numeric & Comparable>(_ keyPath: KeyPath<T, V>, field: String, message: String? = nil) -> ValidationBuilder<T> {
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:185:    func validatePositive<V: Numeric & Comparable>(_ keyPath: KeyPath<T, V>, field: String, message: String? = nil) -> ValidationBuilder<T> {
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:199:    func validateDateNotInPast(_ keyPath: KeyPath<T, Date?>, field: String, allowToday: Bool = true, message: String? = nil) -> ValidationBuilder<T> {
Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:214:    func validateMaxLength(_ keyPath: KeyPath<T, String>, field: String, max: Int, message: String? = nil) -> ValidationBuilder<T> {
Apps/iOS/96Blocks-iOS/App/MainTabView.swift:48:            TaskEditSheet(task: nil)
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:401:        NotificationCenter.default.post(name: .navigateToPlanner, object: nil)
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:145:        metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:204:    func debug(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:209:    func info(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:214:    func warning(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:219:    func error(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:224:    func critical(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:231:    func getLogs(level: LogLevel? = nil, category: LogCategory? = nil, limit: Int = 50) -> [LogEntry] {
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:281:func logDebug(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:288:func logInfo(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:295:func logWarning(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:302:func logError(_ category: LogCategory, _ message: String, metadata: [String: String]? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:328:func logCritical(_ category: LogCategory, _ message: String, error: Error? = nil,
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:330:    var metadata: [String: String]? = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:93:            currentStep = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:137:        timer = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:156:        pausedTime = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:170:        timer = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:184:        currentBlock = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:185:        startTime = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:186:        targetEndTime = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:187:        pausedTime = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:192:        currentStep = nil
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:269:    func completeBlock(actualValue: Decimal? = nil) {
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:427:            if currentBlock == nil {
Apps/iOS/96Blocks-iOS/Models/Task.swift:20:    var actualValueBRL: Decimal? = nil
Apps/iOS/96Blocks-iOS/Models/Task.swift:22:    var dueDate: Date? = nil
Apps/iOS/96Blocks-iOS/Models/Task.swift:23:    var completedAt: Date? = nil
Apps/iOS/96Blocks-iOS/Models/Task.swift:25:    var goalId: UUID? = nil
Apps/iOS/96Blocks-iOS/Models/Task.swift:70:        actualValueBRL: Decimal? = nil,
Apps/iOS/96Blocks-iOS/Models/Task.swift:72:        dueDate: Date? = nil,
Apps/iOS/96Blocks-iOS/Models/Task.swift:73:        goalId: UUID? = nil,
Apps/iOS/96Blocks-iOS/Components/AppTheme.swift:17:        guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { return nil }
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:63:                    NotificationCenter.default.post(name: .showNewTask, object: nil)
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:68:                    NotificationCenter.default.post(name: .showGeneratePlan, object: nil)
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:42:                !(block.status == .completed && block.completedAt == nil),
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:91:            fatalError("Failed to create ModelContainer: \(error)")
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:130:        syncError = nil

[Showing results with pagination = limit: 50, offset: 0]


Let me search for more specific patterns related to incomplete implementations, stub methods, and unimplemented features.


     1→//
     2→//  AIService.swift
     3→//  96Blocks-iOS
     4→//
     5→//  AI Service for generating day plans using multiple AI providers
     6→//  Supports: Claude (Anthropic), OpenAI (GPT-4), Grok (xAI), LM Studio (Local)
     7→//
     8→//  API keys are embedded for TestFlight users - no configuration needed!
     9→//
    10→
    11→import Foundation
    12→
    13→// MARK: - Secure API Key Storage
    14→// API keys are stored securely in Keychain. Users configure keys in Settings.
    15→// For TestFlight: Keys should be set via Settings > AI Configuration
    16→
    17→private struct SecureKeyStore {
    18→    // Default LM Studio URL (can be changed in Settings)
    19→    static let defaultLMStudioURL = "http://192.168.1.96:1234"
    20→
    21→    /// Get API key from Keychain
    22→    static func key(for provider: AIProvider) -> String? {
    23→        switch provider {
    24→        case .grok4, .grok41:
    25→            return KeychainService.get(.grokAPIKey)
    26→        case .openai:
    27→            return KeychainService.get(.openaiAPIKey)
    28→        case .claude:
    29→            return KeychainService.get(.claudeAPIKey)
    30→        case .lmstudio:
    31→            return "local"  // LM Studio doesn't need API key
    32→        }
    33→    }
    34→
    35→    /// Save API key to Keychain
    36→    static func saveKey(_ key: String, for provider: AIProvider) {
    37→        switch provider {
    38→        case .grok4, .grok41:
    39→            KeychainService.save(key, for: .grokAPIKey)
    40→        case .openai:
    41→            KeychainService.save(key, for: .openaiAPIKey)
    42→        case .claude:
    43→            KeychainService.save(key, for: .claudeAPIKey)
    44→        case .lmstudio:
    45→            KeychainService.save(key, for: .lmstudioURL)
    46→        }
    47→    }
    48→
    49→    /// Delete API key from Keychain
    50→    static func deleteKey(for provider: AIProvider) {
    51→        switch provider {
    52→        case .grok4, .grok41:
    53→            KeychainService.delete(.grokAPIKey)
    54→        case .openai:
    55→            KeychainService.delete(.openaiAPIKey)
    56→        case .claude:
    57→            KeychainService.delete(.claudeAPIKey)
    58→        case .lmstudio:
    59→            KeychainService.delete(.lmstudioURL)
    60→        }
    61→    }
    62→
    63→    /// Get LM Studio URL from Keychain or return default
    64→    static var lmStudioURL: String {
    65→        KeychainService.get(.lmstudioURL) ?? defaultLMStudioURL
    66→    }
    67→}
    68→
    69→// MARK: - AI Provider Enum
    70→
    71→enum AIProvider: String, CaseIterable, Codable {
    72→    case grok4 = "Grok 4"
    73→    case grok41 = "Grok 4.1"
    74→    case claude = "Claude"
    75→    case openai = "OpenAI"
    76→    case lmstudio = "LM Studio"
    77→
    78→    var displayName: String {
    79→        switch self {
    80→        case .grok4: return "Grok 4 (xAI)"
    81→        case .grok41: return "Grok 4.1 Fast (xAI)"
    82→        case .claude: return "Claude (Anthropic)"
    83→        case .openai: return "GPT-4 (OpenAI)"
    84→        case .lmstudio: return "LM Studio (Local)"
    85→        }
    86→    }
    87→
    88→    var icon: String {
    89→        switch self {
    90→        case .grok4: return "bolt.fill"
    91→        case .grok41: return "bolt.trianglebadge.exclamationmark.fill"
    92→        case .claude: return "brain.head.profile"
    93→        case .openai: return "sparkles"
    94→        case .lmstudio: return "desktopcomputer"
    95→        }
    96→    }
    97→
    98→    var apiURL: String {
    99→        switch self {
   100→        case .grok4, .grok41: return "https://api.x.ai/v1/chat/completions"

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

//
//  AIService.swift
//  96Blocks-iOS
//
//  AI Service for generating day plans using multiple AI providers
//  Supports: Claude (Anthropic), OpenAI (GPT-4), Grok (xAI), LM Studio (Local)
//
//  API keys are embedded for TestFlight users - no configuration needed!
//

import Foundation

// MARK: - Secure API Key Storage
// API keys are stored securely in Keychain. Users configure keys in Settings.
// For TestFlight: Keys should be set via Settings > AI Configuration

private struct SecureKeyStore {
    // Default LM Studio URL (can be changed in Settings)
    static let defaultLMStudioURL = "http://192.168.1.96:1234"

    /// Get API key from Keychain
    static func key(for provider: AIProvider) -> String? {
        switch provider {
        case .grok4, .grok41:
            return KeychainService.get(.grokAPIKey)
        case .openai:
            return KeychainService.get(.openaiAPIKey)
        case .claude:
            return KeychainService.get(.claudeAPIKey)
        case .lmstudio:
            return "local"  // LM Studio doesn't need API key
        }
    }

    /// Save API key to Keychain
    static func saveKey(_ key: String, for provider: AIProvider) {
        switch provider {
        case .grok4, .grok41:
            KeychainService.save(key, for: .grokAPIKey)
        case .openai:
            KeychainService.save(key, for: .openaiAPIKey)
        case .claude:
            KeychainService.save(key, for: .claudeAPIKey)
        case .lmstudio:
            KeychainService.save(key, for: .lmstudioURL)
        }
    }

    /// Delete API key from Keychain
    static func deleteKey(for provider: AIProvider) {
        switch provider {
        case .grok4, .grok41:
            KeychainService.delete(.grokAPIKey)
        case .openai:
            KeychainService.delete(.openaiAPIKey)
        case .claude:
            KeychainService.delete(.claudeAPIKey)
        case .lmstudio:
            KeychainService.delete(.lmstudioURL)
        }
    }

    /// Get LM Studio URL from Keychain or return default
    static var lmStudioURL: String {
        KeychainService.get(.lmstudioURL) ?? defaultLMStudioURL
    }
}

// MARK: - AI Provider Enum

enum AIProvider: String, CaseIterable, Codable {
    case grok4 = "Grok 4"
    case grok41 = "Grok 4.1"
    case claude = "Claude"
    case openai = "OpenAI"
    case lmstudio = "LM Studio"

    var displayName: String {
        switch self {
        case .grok4: return "Grok 4 (xAI)"
        case .grok41: return "Grok 4.1 Fast (xAI)"
        case .claude: return "Claude (Anthropic)"
        case .openai: return "GPT-4 (OpenAI)"
        case .lmstudio: return "LM Studio (Local)"
        }
    }

    var icon: String {
        switch self {
        case .grok4: return "bolt.fill"
        case .grok41: return "bolt.trianglebadge.exclamationmark.fill"
        case .claude: return "brain.head.profile"
        case .openai: return "sparkles"
        case .lmstudio: return "desktopcomputer"
        }
    }

    var apiURL: String {
        switch self {
        case .grok4, .grok41: return "https://api.x.ai/v1/chat/completions"


Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:26:            // 1. Title is required and not empty
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:136:        // Allow due date to be today or in the future
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:69:        // 6. Due date validation (if set, should be in future for active goals)
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:17:    case missingBlocks = "MISSING_BLOCKS"
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:22:    case futureCompletion = "FUTURE_COMPLETION"
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:29:        case .missingBlocks: return "rectangle.on.rectangle.slash"
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:34:        case .futureCompletion: return "clock.badge.exclamationmark"
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:40:        case .duplicateBlock, .missingBlocks: return .high
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:43:        case .invalidBlockIndex, .negativeValue, .futureCompletion: return .low
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:52:        case .missingBlocks: return "Blocos faltando"
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:57:        case .futureCompletion: return "Data de conclusao no futuro"
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:190:        let missingBlockIssues = checkMissingBlocks(dataManager)
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:191:        issues.append(contentsOf: missingBlockIssues)
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:226:        let futureIssues = checkFutureCompletionDates(dataManager)
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:227:        issues.append(contentsOf: futureIssues)
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:292:            type: .missingBlocks,
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:418:            type: .futureCompletion,
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:467:        case .missingBlocks:
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:481:        case .futureCompletion:
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:231:        // Schedule new reminders for non-empty blocks
Apps/iOS/96Blocks-iOS/Services/AIService.swift:295:            throw AIError.missingAPIKey
Apps/iOS/96Blocks-iOS/Services/AIService.swift:312:            throw AIError.missingAPIKey
Apps/iOS/96Blocks-iOS/Services/AIService.swift:397:                throw AIError.emptyResponse
Apps/iOS/96Blocks-iOS/Services/AIService.swift:404:                throw AIError.emptyResponse
Apps/iOS/96Blocks-iOS/Services/AIService.swift:626:    case missingAPIKey
Apps/iOS/96Blocks-iOS/Services/AIService.swift:629:    case emptyResponse
Apps/iOS/96Blocks-iOS/Services/AIService.swift:639:        case .missingAPIKey:
Apps/iOS/96Blocks-iOS/Services/AIService.swift:645:        case .emptyResponse:
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:223:            // Create missing blocks
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:383:            // Create missing blocks
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:44:                    emptyStateView
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:71:    private var emptyStateView: some View {
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:439:                    .disabled(title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:115:                        .disabled(isGenerating)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/GeneratePlanView.swift:193:                    .disabled(!hasKey)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:253:            .disabled(timerService.currentStepIndex == 0)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/TimerView.swift:386:        // Safe Decimal parsing with fallback to nil (not 0, to distinguish empty from zero)
Apps/iOS/96Blocks-iOS/Components/HapticManager.swift:62:        // Skip if already prepared, not supported, or disabled
Apps/iOS/96Blocks-iOS/Views/DayPlanner/StepListView.swift:283:                    .disabled(title.trimmingCharacters(in: .whitespaces).isEmpty)
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:67:                .disabled(integrityService.isRunning)
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:80:                    .disabled(isFixingAll || integrityService.isRunning)
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:365:                .disabled(isFixing)
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:277:                .disabled(dataManager.isSyncing)
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:470:                    .disabled(title.isEmpty)
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:602:                    .disabled(apiKey.isEmpty && aiService.isUsingDefaultKey())
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:712:                    .disabled(isExporting)
Apps/iOS/96Blocks-iOS/Models/Block.swift:242:    /// Create 96 empty blocks for a given date
Apps/iOS/96Blocks-iOS/App/96BlocksApp.swift:115:                print("⚠ Notification authorization denied - reminders disabled")

[Showing results with pagination = limit: 100, offset: 0]


Now let me read more key files to identify missing features and incomplete implementations.


     1→//
     2→//  SettingsView.swift
     3→//  96Blocks-iOS
     4→//
     5→//  App settings and configuration with Sign in with Apple + iCloud sync
     6→//
     7→
     8→import SwiftUI
     9→import AuthenticationServices
    10→
    11→struct SettingsView: View {
    12→    @EnvironmentObject var dataManager: DataManager
    13→    @StateObject private var aiService = AIService.shared
    14→    @StateObject private var authManager = AuthManager.shared
    15→
    16→    @AppStorage("96Blocks_HapticsEnabled") private var hapticsEnabled = true
    17→    @AppStorage("96Blocks_NotificationsEnabled") private var notificationsEnabled = true
    18→    @AppStorage("96Blocks_WorkStartHour") private var workStartHour = 8
    19→    @AppStorage("96Blocks_WorkEndHour") private var workEndHour = 18
    20→
    21→    @State private var showClearDataAlert = false
    22→    @State private var showExportSheet = false
    23→    @State private var showAPIKeySheet = false
    24→    @State private var showSignOutAlert = false
    25→
    26→    var body: some View {
    27→        NavigationStack {
    28→            Form {
    29→                // Account & iCloud Section
    30→                accountSection
    31→
    32→                // Profile Section
    33→                Section("Perfil de Trabalho") {
    34→                    Picker("Inicio do Expediente", selection: $workStartHour) {
    35→                        ForEach(5..<12, id: \.self) { hour in
    36→                            Text(String(format: "%02d:00", hour)).tag(hour)
    37→                        }
    38→                    }
    39→
    40→                    Picker("Fim do Expediente", selection: $workEndHour) {
    41→                        ForEach(16..<23, id: \.self) { hour in
    42→                            Text(String(format: "%02d:00", hour)).tag(hour)
    43→                        }
    44→                    }
    45→                }
    46→
    47→                // AI Section
    48→                Section {
    49→                    HStack {
    50→                        Image(systemName: "sparkles")
    51→                            .foregroundStyle(.blue)
    52→                        VStack(alignment: .leading, spacing: 2) {
    53→                            Text("Claude AI")
    54→                                .font(.subheadline)
    55→                            Text(aiService.isUsingDefaultKey() ? "Usando chave integrada" : "Usando chave personalizada")
    56→                                .font(.caption)
    57→                                .foregroundStyle(.secondary)
    58→                        }
    59→                        Spacer()
    60→                        Image(systemName: "checkmark.circle.fill")
    61→                            .foregroundStyle(.green)
    62→                    }
    63→
    64→                    if let lastGen = aiService.lastGeneration {
    65→                        HStack {
    66→                            Text("Ultimo uso")
    67→                            Spacer()
    68→                            Text(lastGen, style: .relative)
    69→                                .foregroundStyle(.secondary)
    70→                        }
    71→                    }
    72→
    73→                    Button {
    74→                        showAPIKeySheet = true
    75→                    } label: {
    76→                        HStack {
    77→                            Text("Usar chave personalizada")
    78→                            Spacer()
    79→                            Image(systemName: "chevron.right")
    80→                                .font(.caption)
    81→                                .foregroundStyle(.secondary)
    82→                        }
    83→                    }
    84→                } header: {
    85→                    Text("Inteligencia Artificial")
    86→                } footer: {
    87→                    Text("O Claude AI gera planos de dia otimizados baseados no seu backlog e metas.")
    88→                }
    89→
    90→                // Preferences Section
    91→                Section("Preferencias") {
    92→                    Toggle("Feedback Haptico", isOn: $hapticsEnabled)
    93→                        .onChange(of: hapticsEnabled) { _, newValue in
    94→                            HapticManager.isEnabled = newValue
    95→                            if newValue {
    96→                                HapticManager.selection()
    97→                            }
    98→                        }
    99→
   100→                    Toggle("Notificacoes", isOn: $notificationsEnabled)
   101→                }
   102→
   103→                // Data Section
   104→                Section("Dados") {
   105→                    Button {
   106→                        showExportSheet = true
   107→                    } label: {
   108→                        Label("Exportar Dados", systemImage: "square.and.arrow.up")
   109→                    }
   110→
   111→                    NavigationLink {
   112→                        GoalsListView()
   113→                    } label: {
   114→                        Label("Gerenciar Metas", systemImage: "target")
   115→                    }
   116→
   117→                    NavigationLink {
   118→                        TemplatesListView()
   119→                    } label: {
   120→                        Label("Gerenciar Templates", systemImage: "doc.on.doc")
   121→                    }
   122→
   123→                    NavigationLink {
   124→                        SystemHealthView()
   125→                    } label: {
   126→                        Label("Saude do Sistema", systemImage: "stethoscope")
   127→                    }
   128→                }
   129→
   130→                // Statistics Section
   131→                Section("Estatisticas") {
   132→                    HStack {
   133→                        Text("Tarefas no Backlog")
   134→                        Spacer()
   135→                        Text("\(dataManager.getBacklogTasks().count)")
   136→                            .foregroundStyle(.secondary)
   137→                    }
   138→
   139→                    HStack {
   140→                        Text("Metas Ativas")
   141→                        Spacer()
   142→                        Text("\(dataManager.getActiveGoals().count)")
   143→                            .foregroundStyle(.secondary)
   144→                    }
   145→
   146→                    HStack {
   147→                        Text("Templates")
   148→                        Spacer()
   149→                        Text("\(dataManager.templates.count)")
   150→                            .foregroundStyle(.secondary)

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

//
//  SettingsView.swift
//  96Blocks-iOS
//
//  App settings and configuration with Sign in with Apple + iCloud sync
//

import SwiftUI
import AuthenticationServices

struct SettingsView: View {
    @EnvironmentObject var dataManager: DataManager
    @StateObject private var aiService = AIService.shared
    @StateObject private var authManager = AuthManager.shared

    @AppStorage("96Blocks_HapticsEnabled") private var hapticsEnabled = true
    @AppStorage("96Blocks_NotificationsEnabled") private var notificationsEnabled = true
    @AppStorage("96Blocks_WorkStartHour") private var workStartHour = 8
    @AppStorage("96Blocks_WorkEndHour") private var workEndHour = 18

    @State private var showClearDataAlert = false
    @State private var showExportSheet = false
    @State private var showAPIKeySheet = false
    @State private var showSignOutAlert = false

    var body: some View {
        NavigationStack {
            Form {
                // Account & iCloud Section
                accountSection

                // Profile Section
                Section("Perfil de Trabalho") {
                    Picker("Inicio do Expediente", selection: $workStartHour) {
                        ForEach(5..<12, id: \.self) { hour in
                            Text(String(format: "%02d:00", hour)).tag(hour)
                        }
                    }

                    Picker("Fim do Expediente", selection: $workEndHour) {
                        ForEach(16..<23, id: \.self) { hour in
                            Text(String(format: "%02d:00", hour)).tag(hour)
                        }
                    }
                }

                // AI Section
                Section {
                    HStack {
                        Image(systemName: "sparkles")
                            .foregroundStyle(.blue)
                        VStack(alignment: .leading, spacing: 2) {
                            Text("Claude AI")
                                .font(.subheadline)
                            Text(aiService.isUsingDefaultKey() ? "Usando chave integrada" : "Usando chave personalizada")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }
                        Spacer()
                        Image(systemName: "checkmark.circle.fill")
                            .foregroundStyle(.green)
                    }

                    if let lastGen = aiService.lastGeneration {
                        HStack {
                            Text("Ultimo uso")
                            Spacer()
                            Text(lastGen, style: .relative)
                                .foregroundStyle(.secondary)
                        }
                    }

                    Button {
                        showAPIKeySheet = true
                    } label: {
                        HStack {
                            Text("Usar chave personalizada")
                            Spacer()
                            Image(systemName: "chevron.right")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }
                    }
                } header: {
                    Text("Inteligencia Artificial")
                } footer: {
                    Text("O Claude AI gera planos de dia otimizados baseados no seu backlog e metas.")
                }

                // Preferences Section
                Section("Preferencias") {
                    Toggle("Feedback Haptico", isOn: $hapticsEnabled)
                        .onChange(of: hapticsEnabled) { _, newValue in
                            HapticManager.isEnabled = newValue
                            if newValue {
                                HapticManager.selection()
                            }
                        }

                    Toggle("Notificacoes", isOn: $notificationsEnabled)
                }

                // Data Section
                Section("Dados") {
                    Button {
                        showExportSheet = true
                    } label: {
                        Label("Exportar Dados", systemImage: "square.and.arrow.up")
                    }

                    NavigationLink {
                        GoalsListView()
                    } label: {
                        Label("Gerenciar Metas", systemImage: "target")
                    }

                    NavigationLink {
                        TemplatesListView()
                    } label: {
                        Label("Gerenciar Templates", systemImage: "doc.on.doc")
                    }

                    NavigationLink {
                        SystemHealthView()
                    } label: {
                        Label("Saude do Sistema", systemImage: "stethoscope")
                    }
                }

                // Statistics Section
                Section("Estatisticas") {
                    HStack {
                        Text("Tarefas no Backlog")
                        Spacer()
                        Text("\(dataManager.getBacklogTasks().count)")
                            .foregroundStyle(.secondary)
                    }

                    HStack {
                        Text("Metas Ativas")
                        Spacer()
                        Text("\(dataManager.getActiveGoals().count)")
                            .foregroundStyle(.secondary)
                    }

                    HStack {
                        Text("Templates")
                        Spacer()
                        Text("\(dataManager.templates.count)")
                            .foregroundStyle(.secondary)


     1→//
     2→//  OnboardingView.swift
     3→//  96Blocks-iOS
     4→//
     5→//  Onboarding flow for new users
     6→//
     7→
     8→import SwiftUI
     9→import UserNotifications
    10→
    11→struct OnboardingView: View {
    12→    @AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding = false
    13→    @State private var currentPage = 0
    14→
    15→    private let totalPages = 7
    16→
    17→    var body: some View {
    18→        ZStack {
    19→            // Background gradient
    20→            LinearGradient(
    21→                colors: [Color.blue.opacity(0.1), Color.white],
    22→                startPoint: .top,
    23→                endPoint: .bottom
    24→            )
    25→            .ignoresSafeArea()
    26→
    27→            VStack(spacing: 0) {
    28→                // Page content
    29→                TabView(selection: $currentPage) {
    30→                    WelcomePage(onNext: nextPage)
    31→                        .tag(0)
    32→
    33→                    ConceptPage(onNext: nextPage)
    34→                        .tag(1)
    35→
    36→                    ROIPage(onNext: nextPage)
    37→                        .tag(2)
    38→
    39→                    SetupPage(onNext: nextPage)
    40→                        .tag(3)
    41→
    42→                    PermissionsPage(onNext: nextPage)
    43→                        .tag(4)
    44→
    45→                    APIKeyPage(onNext: nextPage)
    46→                        .tag(5)
    47→
    48→                    CompletePage(onComplete: completeOnboarding)
    49→                        .tag(6)
    50→                }
    51→                .tabViewStyle(.page(indexDisplayMode: .never))
    52→                .animation(.easeInOut, value: currentPage)
    53→
    54→                // Custom page indicator
    55→                HStack(spacing: 8) {
    56→                    ForEach(0..<totalPages, id: \.self) { index in
    57→                        Circle()
    58→                            .fill(index == currentPage ? Color.blue : Color.gray.opacity(0.3))
    59→                            .frame(width: 8, height: 8)
    60→                            .scaleEffect(index == currentPage ? 1.2 : 1.0)
    61→                            .animation(.spring(), value: currentPage)
    62→                    }
    63→                }
    64→                .padding(.bottom, 30)
    65→            }
    66→        }
    67→    }
    68→
    69→    private func nextPage() {
    70→        withAnimation {
    71→            if currentPage < totalPages - 1 {
    72→                currentPage += 1
    73→            }
    74→        }
    75→    }
    76→
    77→    private func completeOnboarding() {
    78→        hasCompletedOnboarding = true
    79→    }
    80→}
    81→
    82→// MARK: - Welcome Page
    83→
    84→struct WelcomePage: View {
    85→    let onNext: () -> Void
    86→
    87→    var body: some View {
    88→        VStack(spacing: 30) {
    89→            Spacer()
    90→
    91→            // Logo/Icon
    92→            ZStack {
    93→                Circle()
    94→                    .fill(LinearGradient(
    95→                        colors: [.blue, .blue.opacity(0.7)],
    96→                        startPoint: .topLeading,
    97→                        endPoint: .bottomTrailing
    98→                    ))
    99→                    .frame(width: 120, height: 120)
   100→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

//
//  OnboardingView.swift
//  96Blocks-iOS
//
//  Onboarding flow for new users
//

import SwiftUI
import UserNotifications

struct OnboardingView: View {
    @AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding = false
    @State private var currentPage = 0

    private let totalPages = 7

    var body: some View {
        ZStack {
            // Background gradient
            LinearGradient(
                colors: [Color.blue.opacity(0.1), Color.white],
                startPoint: .top,
                endPoint: .bottom
            )
            .ignoresSafeArea()

            VStack(spacing: 0) {
                // Page content
                TabView(selection: $currentPage) {
                    WelcomePage(onNext: nextPage)
                        .tag(0)

                    ConceptPage(onNext: nextPage)
                        .tag(1)

                    ROIPage(onNext: nextPage)
                        .tag(2)

                    SetupPage(onNext: nextPage)
                        .tag(3)

                    PermissionsPage(onNext: nextPage)
                        .tag(4)

                    APIKeyPage(onNext: nextPage)
                        .tag(5)

                    CompletePage(onComplete: completeOnboarding)
                        .tag(6)
                }
                .tabViewStyle(.page(indexDisplayMode: .never))
                .animation(.easeInOut, value: currentPage)

                // Custom page indicator
                HStack(spacing: 8) {
                    ForEach(0..<totalPages, id: \.self) { index in
                        Circle()
                            .fill(index == currentPage ? Color.blue : Color.gray.opacity(0.3))
                            .frame(width: 8, height: 8)
                            .scaleEffect(index == currentPage ? 1.2 : 1.0)
                            .animation(.spring(), value: currentPage)
                    }
                }
                .padding(.bottom, 30)
            }
        }
    }

    private func nextPage() {
        withAnimation {
            if currentPage < totalPages - 1 {
                currentPage += 1
            }
        }
    }

    private func completeOnboarding() {
        hasCompletedOnboarding = true
    }
}

// MARK: - Welcome Page

struct WelcomePage: View {
    let onNext: () -> Void

    var body: some View {
        VStack(spacing: 30) {
            Spacer()

            // Logo/Icon
            ZStack {
                Circle()
                    .fill(LinearGradient(
                        colors: [.blue, .blue.opacity(0.7)],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    ))
                    .frame(width: 120, height: 120)


Let me search for tests, localization, and integration features.


find /Users/neog/Apps/iOS/96Blocks-iOS -type f \( -name "*Test*" -o -name "*test*" -o -name "*.strings" -o -name "*Localizable*" \) 2>/dev/null

Search for test files and localization files


Apps/iOS/96Blocks-iOS/Services/Validation/ValidationResult.swift:202:        let comparison = allowToday ? Calendar.current.startOfDay(for: Date()) : Date()
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:137:        let today = Calendar.current.startOfDay(for: Date())
Apps/iOS/96Blocks-iOS/Services/Validation/TaskValidator.swift:138:        let dueDateStart = Calendar.current.startOfDay(for: dueDate)
Apps/iOS/96Blocks-iOS/Services/Validation/BlockValidator.swift:104:        guard let oneYearAgo = Calendar.current.date(byAdding: .year, value: -maxPastYears, to: Date()) else {
Apps/iOS/96Blocks-iOS/Services/Validation/GoalValidator.swift:200:        guard let pastLimit = Calendar.current.date(byAdding: .day, value: -maxPastDays, to: Date()) else {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:165:    func runFullCheck() async -> IntegrityReport {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:453:    func autoFix(issue: IntegrityIssue) async -> Bool {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:489:    private func fixOrphanedBlockSteps(_ dataManager: DataManager, ids: [UUID]) async -> Bool {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:500:    private func fixDuplicateBlocks(_ dataManager: DataManager, ids: [UUID]) async -> Bool {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:522:    private func fixInvalidReferences(_ dataManager: DataManager, ids: [UUID]) async -> Bool {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:538:    private func fixNegativeValues(_ dataManager: DataManager, ids: [UUID]) async -> Bool {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:556:    private func fixFutureCompletionDates(_ dataManager: DataManager, ids: [UUID]) async -> Bool {
Apps/iOS/96Blocks-iOS/Services/IntegrityService.swift:572:    func fixAllIssues() async -> Int {
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:5://  Authentication manager with Sign in with Apple + iCloud sync
Apps/iOS/96Blocks-iOS/Services/AuthManager.swift:52:    private func verifyCredentials(userID: String) async {
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:23:    func requestAuthorization() async -> Bool {
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:46:    // MARK: - Block Reminders
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:67:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:82:        let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:121:        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:160:        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:223:    // MARK: - Schedule Day Reminders
Apps/iOS/96Blocks-iOS/Services/NotificationService.swift:226:    func scheduleDayReminders(for blocks: [Block], minutesBefore: Int = 5) {
Apps/iOS/96Blocks-iOS/Services/AIService.swift:244:    ) async throws -> [GeneratedBlock] {
Apps/iOS/96Blocks-iOS/Services/AIService.swift:310:    private func generateWithProvider(_ provider: AIProvider, prompt: String) async throws -> [GeneratedBlock] {
Apps/iOS/96Blocks-iOS/Services/TimerService.swift:52:        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:50:    case sync = "SYNC"
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:63:        case .sync: return "☁"
Apps/iOS/96Blocks-iOS/Services/LoggingService.swift:260:    // MARK: - Export
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:43:    @Published var syncError: String?
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:45:    // Combine-based debounce for CloudKit sync (more robust than manual date tracking)
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:65:            // Configure CloudKit sync
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:82:            // Setup sync monitoring
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:86:            print("DataManager: Initialized with CloudKit sync enabled")
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:98:        // Setup Combine debounce pipeline for smoother sync handling
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:127:    /// Manually trigger sync (for pull-to-refresh)
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:130:        syncError = nil
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:132:        // SwiftData + CloudKit syncs automatically, but we can refresh data
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:136:        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:205:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:225:            let today = Calendar.current.startOfDay(for: Date())
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:376:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:432:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:576:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:654:                dueDate: Calendar.current.date(byAdding: .day, value: 2, to: Date())
Apps/iOS/96Blocks-iOS/Services/DataManager.swift:676:            dueDate: Calendar.current.date(byAdding: .month, value: 1, to: Date())
Apps/iOS/96Blocks-iOS/Views/Analytics/AnalyticsView.swift:261:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:383:            DispatchQueue.main.async {
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:394:            DispatchQueue.main.async {
Apps/iOS/96Blocks-iOS/Views/Onboarding/OnboardingView.swift:543:            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
Apps/iOS/96Blocks-iOS/Models/DailySummary.swift:100:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Views/Backlog/BacklogView.swift:323:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Models/Goal.swift:77:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Models/Block.swift:111:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Models/Block.swift:124:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Models/Block.swift:251:        let calendar = Calendar.current
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:183:                ShareLink(item: loggingService.exportLogsAsText()) {
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:184:                    Label("Exportar Logs", systemImage: "square.and.arrow.up")
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:318:    private func fixIssue(_ issue: IntegrityIssue) async {
Apps/iOS/96Blocks-iOS/Views/Settings/SystemHealthView.swift:328:    let onFix: () async -> Void
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:123:            if Calendar.current.isDateInToday(dataManager.selectedDate) {
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:214:        let isToday = Calendar.current.isDateInToday(dataManager.selectedDate)
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:363:                if scrollToCurrentBlock && Calendar.current.isDateInToday(dataManager.selectedDate) {
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:402:        if let newDate = Calendar.current.date(byAdding: .day, value: -1, to: dataManager.selectedDate) {
Apps/iOS/96Blocks-iOS/Views/DayPlanner/DayPlannerView.swift:411:        if let newDate = Calendar.current.date(byAdding: .day, value: 1, to: dataManager.selectedDate) {
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:5://  App settings and configuration with Sign in with Apple + iCloud sync
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:22:    @State private var showExportSheet = false
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:106:                        showExportSheet = true
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:108:                        Label("Exportar Dados", systemImage: "square.and.arrow.up")
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:201:            .sheet(isPresented: $showExportSheet) {
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:202:                ExportSheet()
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:245:                // iCloud sync status
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:478:        let dueDate = Calendar.current.date(byAdding: .day, value: timeframe.defaultDays, to: Date())
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:610:// MARK: - Export Sheet
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:611:struct ExportSheet: View {
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:615:    @State private var exportFormat: ExportFormat = .json
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:616:    @State private var exportScope: ExportScope = .all
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:618:    @State private var isExporting = false
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:620:    @State private var showShareSheet = false
Apps/iOS/96Blocks-iOS/Views/Settings/SettingsView.swift:623:    enum ExportFormat: String, CaseIterable {

[Showing results with pagination = limit: 80, offset: 0]


Let me continue reading the export functionality and check for more details about incomplete features.


Grep

widget|home screen|notification|reminder|alert|ios app|lock screen


   600→                        dismiss()
   601→                    }
   602→                    .disabled(apiKey.isEmpty && aiService.isUsingDefaultKey())
   603→                }
   604→            }
   605→        }
   606→        .presentationDetents([.medium])
   607→    }
   608→}
   609→
   610→// MARK: - Export Sheet
   611→struct ExportSheet: View {
   612→    @EnvironmentObject var dataManager: DataManager
   613→    @Environment(\.dismiss) private var dismiss
   614→
   615→    @State private var exportFormat: ExportFormat = .json
   616→    @State private var exportScope: ExportScope = .all
   617→    @State private var dateRange: DateRange = .week
   618→    @State private var isExporting = false
   619→    @State private var exportedURL: URL?
   620→    @State private var showShareSheet = false
   621→    @State private var exportError: String?
   622→
   623→    enum ExportFormat: String, CaseIterable {
   624→        case json = "JSON"
   625→        case csv = "CSV"
   626→
   627→        var fileExtension: String {
   628→            rawValue.lowercased()
   629→        }
   630→
   631→        var mimeType: String {
   632→            self == .json ? "application/json" : "text/csv"
   633→        }
   634→    }
   635→
   636→    enum ExportScope: String, CaseIterable {
   637→        case all = "Todos os Dados"
   638→        case blocks = "Apenas Blocos"
   639→        case tasks = "Apenas Tarefas"
   640→        case goals = "Apenas Metas"
   641→    }
   642→
   643→    enum DateRange: String, CaseIterable {
   644→        case week = "Ultima Semana"
   645→        case month = "Ultimo Mes"
   646→        case all = "Todo Historico"
   647→
   648→        var days: Int? {
   649→            switch self {
   650→            case .week: return 7
   651→            case .month: return 30
   652→            case .all: return nil
   653→            }
   654→        }
   655→    }
   656→
   657→    var body: some View {
   658→        NavigationStack {
   659→            Form {
   660→                Section {
   661→                    Picker("Formato", selection: $exportFormat) {
   662→                        ForEach(ExportFormat.allCases, id: \.self) { format in
   663→                            Text(format.rawValue).tag(format)
   664→                        }
   665→                    }
   666→                    .pickerStyle(.segmented)
   667→                } header: {
   668→                    Text("Formato de Exportacao")
   669→                } footer: {
   670→                    Text(exportFormat == .json
   671→                         ? "JSON preserva toda a estrutura dos dados, ideal para backup."
   672→                         : "CSV pode ser aberto em planilhas como Excel ou Google Sheets.")
   673→                }
   674→
   675→                Section("Escopo") {
   676→                    Picker("Dados", selection: $exportScope) {
   677→                        ForEach(ExportScope.allCases, id: \.self) { scope in
   678→                            Text(scope.rawValue).tag(scope)
   679→                        }
   680→                    }
   681→                }
   682→
   683→                if exportScope == .blocks || exportScope == .all {
   684→                    Section("Periodo") {
   685→                        Picker("Periodo", selection: $dateRange) {
   686→                            ForEach(DateRange.allCases, id: \.self) { range in
   687→                                Text(range.rawValue).tag(range)
   688→                            }
   689→                        }
   690→                    }
   691→                }
   692→
   693→                Section {
   694→                    exportSummary
   695→                }
   696→
   697→                Section {
   698→                    Button {
   699→                        performExport()
   700→                    } label: {
   701→                        HStack {
   702→                            Spacer()
   703→                            if isExporting {
   704→                                ProgressView()
   705→                                    .progressViewStyle(CircularProgressViewStyle())
   706→                            } else {
   707→                                Label("Exportar Agora", systemImage: "square.and.arrow.up")
   708→                            }
   709→                            Spacer()
   710→                        }
   711→                    }
   712→                    .disabled(isExporting)
   713→                }
   714→
   715→                if let error = exportError {
   716→                    Section {
   717→                        Text(error)
   718→                            .foregroundStyle(.red)
   719→                    }
   720→                }
   721→            }
   722→            .navigationTitle("Exportar Dados")
   723→            .navigationBarTitleDisplayMode(.inline)
   724→            .toolbar {
   725→                ToolbarItem(placement: .topBarTrailing) {
   726→                    Button("Fechar") {
   727→                        dismiss()
   728→                    }
   729→                }
   730→            }
   731→            .sheet(isPresented: $showShareSheet) {
   732→                if let url = exportedURL {
   733→                    ShareSheet(activityItems: [url])
   734→                }
   735→            }
   736→        }
   737→        .presentationDetents([.medium, .large])
   738→    }
   739→
   740→    private var exportSummary: some View {
   741→        let (blocksCount, tasksCount, goalsCount) = getExportCounts()
   742→
   743→        return VStack(alignment: .leading, spacing: 8) {
   744→            Text("Resumo da Exportacao")
   745→                .font(.headline)
   746→
   747→            HStack {
   748→                Image(systemName: "calendar")
   749→                    .foregroundStyle(.blue)
   750→                Text("\(blocksCount) blocos")
   751→                Spacer()
   752→            }
   753→            .font(.subheadline)
   754→
   755→            HStack {
   756→                Image(systemName: "checklist")
   757→                    .foregroundStyle(.orange)
   758→                Text("\(tasksCount) tarefas")
   759→                Spacer()
   760→            }
   761→            .font(.subheadline)
   762→
   763→            HStack {
   764→                Image(systemName: "target")
   765→                    .foregroundStyle(.green)
   766→                Text("\(goalsCount) metas")
   767→                Spacer()
   768→            }
   769→            .font(.subheadline)
   770→        }
   771→    }
   772→
   773→    private func getExportCounts() -> (Int, Int, Int) {
   774→        let blocks = getFilteredBlocks().count
   775→        let tasks = exportScope == .blocks ? 0 : dataManager.tasks.count
   776→        let goals = exportScope == .blocks || exportScope == .tasks ? 0 : dataManager.goals.count
   777→
   778→        return (
   779→            exportScope == .tasks || exportScope == .goals ? 0 : blocks,
   780→            exportScope == .blocks || exportScope == .goals ? 0 : tasks,
   781→            exportScope == .blocks || exportScope == .tasks ? 0 : goals
   782→        )
   783→    }
   784→
   785→    private func getFilteredBlocks() -> [Block] {
   786→        guard let days = dateRange.days else {
   787→            return dataManager.blocks
   788→        }
   789→
   790→        let cutoffDate = Calendar.current.date(byAdding: .day, value: -days, to: Date()) ?? Date()
   791→        return dataManager.blocks.filter { $0.blockDate >= cutoffDate }
   792→    }
   793→
   794→    private func performExport() {
   795→        isExporting = true
   796→        exportError = nil
   797→
   798→        Task {
   799→            do {

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

                        dismiss()
                    }
                    .disabled(apiKey.isEmpty && aiService.isUsingDefaultKey())
                }
            }
        }
        .presentationDetents([.medium])
    }
}

// MARK: - Export Sheet
struct ExportSheet: View {
    @EnvironmentObject var dataManager: DataManager
    @Environment(\.dismiss) private var dismiss

    @State private var exportFormat: ExportFormat = .json
    @State private var exportScope: ExportScope = .all
    @State private var dateRange: DateRange = .week
    @State private var isExporting = false
    @State private var exportedURL: URL?
    @State private var showShareSheet = false
    @State private var exportError: String?

    enum ExportFormat: String, CaseIterable {
        case json = "JSON"
        case csv = "CSV"

        var fileExtension: String {
            rawValue.lowercased()
        }

        var mimeType: String {
            self == .json ? "application/json" : "text/csv"
        }
    }

    enum ExportScope: String, CaseIterable {
        case all = "Todos os Dados"
        case blocks = "Apenas Blocos"
        case tasks = "Apenas Tarefas"
        case goals = "Apenas Metas"
    }

    enum DateRange: String, CaseIterable {
        case week = "Ultima Semana"
        case month = "Ultimo Mes"
        case all = "Todo Historico"

        var days: Int? {
            switch self {
            case .week: return 7
            case .month: return 30
            case .all: return nil
            }
        }
    }

    var body: some View {
        NavigationStack {
            Form {
                Section {
                    Picker("Formato", selection: $exportFormat) {
                        ForEach(ExportFormat.allCases, id: \.self) { format in
                            Text(format.rawValue).tag(format)
                        }
                    }
                    .pickerStyle(.segmented)
                } header: {
                    Text("Formato de Exportacao")
                } footer: {
                    Text(exportFormat == .json
                         ? "JSON preserva toda a estrutura dos dados, ideal para backup."
                         : "CSV pode ser aberto em planilhas como Excel ou Google Sheets.")
                }

                Section("Escopo") {
                    Picker("Dados", selection: $exportScope) {
                        ForEach(ExportScope.allCases, id: \.self) { scope in
                            Text(scope.rawValue).tag(scope)
                        }
                    }
                }

                if exportScope == .blocks || exportScope == .all {
                    Section("Periodo") {
                        Picker("Periodo", selection: $dateRange) {
                            ForEach(DateRange.allCases, id: \.self) { range in
                                Text(range.rawValue).tag(range)
                            }
                        }
                    }
                }

                Section {
                    exportSummary
                }

                Section {
                    Button {
                        performExport()
                    } label: {
                        HStack {
                            Spacer()
                            if isExporting {
                                ProgressView()
                                    .progressViewStyle(CircularProgressViewStyle())
                            } else {
                                Label("Exportar Agora", systemImage: "square.and.arrow.up")
                            }
                            Spacer()
                        }
                    }
                    .disabled(isExporting)
                }

                if let error = exportError {
                    Section {
                        Text(error)
                            .foregroundStyle(.red)
                    }
                }
            }
            .navigationTitle("Exportar Dados")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Fechar") {
                        dismiss()
                    }
                }
            }
            .sheet(isPresented: $showShareSheet) {
                if let url = exportedURL {
                    ShareSheet(activityItems: [url])
                }
            }
        }
        .presentationDetents([.medium, .large])
    }

    private var exportSummary: some View {
        let (blocksCount, tasksCount, goalsCount) = getExportCounts()

        return VStack(alignment: .leading, spacing: 8) {
            Text("Resumo da Exportacao")
                .font(.headline)

            HStack {
                Image(systemName: "calendar")
                    .foregroundStyle(.blue)
                Text("\(blocksCount) blocos")
                Spacer()
            }
            .font(.subheadline)

            HStack {
                Image(systemName: "checklist")
                    .foregroundStyle(.orange)
                Text("\(tasksCount) tarefas")
                Spacer()
            }
            .font(.subheadline)

            HStack {
                Image(systemName: "target")
                    .foregroundStyle(.green)
                Text("\(goalsCount) metas")
                Spacer()
            }
            .font(.subheadline)
        }
    }

    private func getExportCounts() -> (Int, Int, Int) {
        let blocks = getFilteredBlocks().count
        let tasks = exportScope == .blocks ? 0 : dataManager.tasks.count
        let goals = exportScope == .blocks || exportScope == .tasks ? 0 : dataManager.goals.count

        return (
            exportScope == .tasks || exportScope == .goals ? 0 : blocks,
            exportScope == .blocks || exportScope == .goals ? 0 : tasks,
            exportScope == .blocks || exportScope == .tasks ? 0 : goals
        )
    }

    private func getFilteredBlocks() -> [Block] {
        guard let days = dateRange.days else {
            return dataManager.blocks
        }

        let cutoffDate = Calendar.current.date(byAdding: .day, value: -days, to: Date()) ?? Date()
        return dataManager.blocks.filter { $0.blockDate >= cutoffDate }
    }

    private func performExport() {
        isExporting = true
        exportError = nil

        Task {
            do {