# Feels - iOS Mood Tracking App

## Overview

**Feels** is a daily mood tracking iOS application that allows users to rate their emotional state each day on a 5-point scale (Horrible, Bad, Average, Good, Great) and visualize patterns over time through multiple view modes.

## Core Features

- **Daily Mood Tracking**: Rate your day on a 5-point scale
- **Multiple View Modes**: Day (chronological list), Month (calendar grid), Year (aggregate stats)
- **Customization**: Themes, color schemes, icon packs, notification personalities
- **Widgets**: iOS home screen widgets showing recent moods
- **Local Notifications**: Daily reminders with action buttons for quick mood entry
- **Data Export/Import**: CSV format for data portability
- **Subscription Model**: 30-day free trial, then monthly/yearly subscriptions
- **Localization**: English and Spanish

---

## Architecture

**Pattern**: MVVM (Model-View-ViewModel) with SwiftUI

### Project Structure

```
Feels/
├── Shared/                     # Core app code
│   ├── Models/                 # Data models (Mood, Theme, MoodTintable, etc.)
│   ├── Views/                  # SwiftUI views organized by feature
│   │   ├── DayView/           # Chronological list view
│   │   ├── MonthView/         # Calendar grid view
│   │   ├── YearView/          # Yearly statistics view
│   │   ├── CustomizeView/     # Settings and customization
│   │   └── Components/        # Reusable UI components
│   ├── Persisence/            # Core Data persistence layer
│   ├── Onboarding/            # First-run experience
│   └── Protocols/             # Protocol definitions
├── FeelsWidget/               # iOS Widget Extension (3 widget types)
├── en.lproj/                  # English localization
├── es.lproj/                  # Spanish localization
└── Tests iOS/                 # Test targets
```

---

## Key Files

### App Entry
| File | Purpose |
|------|---------|
| `FeelsApp.swift` | Main app entry, Core Data setup, IAP manager, tab navigation |

### Data Layer
| File | Purpose |
|------|---------|
| `Feels.xcdatamodeld` | Core Data model with `MoodEntry` entity |
| `Persistence.swift` | Core Data stack, App Group container |
| `PersistenceGET.swift` | Fetch operations |
| `PersistenceADD.swift` | Create/fill missing entries |
| `PersistenceUPDATE.swift` | Update operations |
| `PersistenceDELETE.swift` | Delete operations |

### Main Views
| File | Purpose |
|------|---------|
| `MainTabView.swift` | Root navigation (Day, Month, Year, Customize tabs) |
| `DayView.swift` | Chronological mood list with edit/delete |
| `MonthView.swift` | Calendar grid with color-coded moods |
| `YearView.swift` | Aggregate yearly statistics |
| `CustomizeView.swift` | Theme, colors, icons, shape settings |

### Services
| File | Purpose |
|------|---------|
| `IAPManager.swift` | StoreKit 2 subscriptions, 30-day trial |
| `LocalNotification.swift` | Daily reminders with quick actions |
| `BGTask.swift` | Background task for filling missing dates |
| `EventLogger.swift` | Analytics event tracking |

---

## Data Models

### MoodEntry (Core Data Entity)
```
- moodValue: Int16 (0-4 for mood ratings)
- forDate: Date (the day being rated)
- timestamp: Date (when entry was created)
- weekDay: Int16 (1-7)
- canEdit, canDelete: Boolean
- entryType: Int16 (header, list, filled-in-missing)
```

### Mood Enum
```swift
enum Mood: Int {
    case horrible = 0
    case bad = 1
    case average = 2
    case good = 3
    case great = 4
    case missing = 5
    case placeholder = 6
}
```

---

## Customization System

### Themes (`Theme.swift`)
- System, iFeel (gradient), Dark, Light
- Protocol: `Themeable`

### Color Schemes (`MoodTintable.swift`)
- Default, Neon, Pastel, Custom (user-defined)
- Each mood has primary and secondary colors

### Icon Packs (`MoodImagable.swift`)
- FontAwesome, Emoji, Hand Emoji
- Protocol: `MoodImagable`

### Shapes
- Circle, Square, Diamond for calendar visualization

### Notification Personalities (`PersonalityPackable.swift`)
- "Nice": Friendly text
- "Rude": Sarcastic/aggressive text

---

## Widget System

Three widget types in `FeelsWidget/`:
1. **FeelsWidget**: Small/Medium/Large showing recent moods
2. **FeelsGraphicWidget**: Small widget with mood graphic
3. **FeelsIconWidget**: Custom icon widget

Data shared via App Groups: `group.com.88oakapps.feels`

---

## Dependencies

### Apple Frameworks
- SwiftUI, CoreData, WidgetKit, StoreKit, UserNotifications, CloudKit, BackgroundTasks

### Third-Party
- CloudKitSyncMonitor
- Firebase (GoogleService-Info.plist)

---

## Configuration

### App Groups
- Production: `group.com.88oakapps.feels`
- Debug: `group.com.88oakapps.feels.debug`

### Background Tasks
- Identifier: `com.88oak.Feels.dbUpdateMissing`

### StoreKit Products
- Monthly subscription
- Yearly subscription
- 30-day free trial

---

## Data Flow

```
User Input → Persistence (Core Data) → ViewModel Update → SwiftUI Re-render
                    ↓
            Widget Update (WidgetCenter.shared.reloadAllTimelines())
```

---

## Localization

| Language | File |
|----------|------|
| English | `en.lproj/Localizable.strings` |
| Spanish | `es.lproj/Localizable.strings` |

Covers: Onboarding, mood names, UI labels, notifications, settings

---

## Notable Implementation Details

1. **Automatic Missing Date Fill**: Creates placeholder entries for days without ratings
2. **Entry Types**: `header`, `listView`, `filledInMissing` - tracks how entries were created
3. **Day Filtering**: Users can filter which weekdays appear in visualizations
4. **CSV Export**: Full data portability with all metadata preserved
