# Dating View Romantic Redesign

**Date:** November 12, 2025
**Project:** BaoLife iOS Application
**Feature:** Dating Tab - In-Relationship View Redesign
**Design Approach:** Romance-First Hero Layout
**Estimated Effort:** 4-5 hours

---

## Executive Summary

This document specifies a complete redesign of the DatingView when a player is in a relationship. The current implementation is functional but lacks emotional impact and visual cohesion. The new design adopts a "Romance-First Hero Layout" that puts the partner at center stage with romantic, cozy aesthetics while maintaining all existing functionality.

**Key Goals:**
- Create emotional connection through romantic visual design
- Maintain cozy design system consistency
- Improve information hierarchy and usability
- Preserve all existing functionality (no breaking changes)
- Enable quick access to primary relationship actions

**What Changes:**
- DatingView.swift: Refactor in-relationship branch only
- Add 4 new modular components in Features/Dating/Components/

**What Stays The Same:**
- Single state view (unchanged)
- All WebSocket message handling
- All modal/sheet presentations
- Analytics tracking
- RelationshipDetailView (separate, detailed view)

---

## Design Rationale

### Why Romance-First Hero Layout?

After analyzing three design approaches, the Romance-First Hero Layout was selected because it:

1. **Balances emotion with usability** - Partner feels special without sacrificing clarity
2. **Leverages existing design system** - Uses BaseCard, gradients, icons already in codebase
3. **Quick to implement** - Similar structure to RelationshipDetailView
4. **Aligns with cozy aesthetic** - Soft, warm, inviting
5. **Mobile-friendly** - Natural scrolling flow with logical sections
6. **Supports future features** - Easy to add notifications, special events, achievements

### Comparison to Current Implementation

**Current DatingView (In Relationship):**
- Partner image (200x200)
- Text-heavy relationship message
- Timeline section with events
- Details section (notes, score, common interests, challenges, future plans)
- Action buttons (Date, Mini Game, Gift, Break Up)

**Issues:**
- No clear visual hierarchy
- Information overload in single scroll
- Actions mixed with information
- Lacks romantic/emotional design
- Partner doesn't feel "special"

**New Design:**
- Partner hero card with romantic styling (spotlight moment)
- Quick action pills (clear CTAs)
- Snapshot stats (at-a-glance metrics)
- Recent moments (emotional connection)
- View details button (progressive disclosure)

**Improvements:**
- Clear visual hierarchy (hero → actions → insights)
- Progressive disclosure (overview here, details in DetailView)
- Romantic visual language (gradients, hearts, warm colors)
- Distinct action zone
- Partner front-and-center

---

## Architecture

### Component Structure

```
DatingView.swift (refactored)
├─ When in relationship:
│  ├─ RomanticHeroCard          [New component]
│  ├─ QuickActionsBar            [New component]
│  ├─ RelationshipSnapshotCard   [New component]
│  ├─ RecentMomentsCard          [New component]
│  └─ View Details Button        [Existing navigation]
│
└─ When single: [Unchanged]
   ├─ EmptyState
   └─ MatchesList
```

### File Organization

```
Features/Dating/
  Components/
    CompatibilityBadge.swift           [Existing]
    CompatibilityExplanationView.swift [Existing]
    EnhancedProfileCard.swift          [Existing]
    InterestTag.swift                  [Existing]
    MatchExplanationToast.swift        [Existing]
    RelationshipEventModal.swift       [Existing]
    StatBadge.swift                    [Existing]
    RomanticHeroCard.swift             [NEW]
    QuickActionsBar.swift              [NEW]
    RelationshipSnapshotCard.swift     [NEW]
    RecentMomentsCard.swift            [NEW]
  Views/
    DateActivitySelectionView.swift    [Existing]
    DateMiniGameView.swift             [Existing]
    DatingView.swift                   [REFACTOR]
    RelationshipDetailView.swift       [Existing - unchanged]
    RelationshipsView.swift            [Existing]
    SwipeDatingView.swift              [Existing]
```

### Design Principles

1. **Single Responsibility** - Each component has one clear purpose
2. **Reusability** - Components are self-contained and reusable
3. **Consistency** - Uses existing design system (AppColors, AppSpacing, typography)
4. **Progressive Disclosure** - Overview in DatingView, details in RelationshipDetailView
5. **No Breaking Changes** - All existing functionality preserved

---

## Component Specifications

### Component 1: RomanticHeroCard

**Purpose:** Showcase the partner with romantic, cozy aesthetics that make them feel special.

**File:** `Features/Dating/Components/RomanticHeroCard.swift`

**API:**
```swift
struct RomanticHeroCard: View {
    let partner: Person
    let relationship: Relationship
    var showHeartAnimation: Bool = true

    var body: some View
}
```

**Layout:**
```
┌─────────────────────────────────────────┐
│  BaseCard with gradient background      │
│  ┌─────────────────────────────────┐    │
│  │  Soft pink/purple gradient      │    │
│  │  (romantic atmosphere)          │    │
│  │                                 │    │
│  │     ✨ Optional floating        │    │
│  │        heart particles          │    │
│  │                                 │    │
│  │   ┌─────────────────────┐       │    │
│  │   │   Partner Avatar    │       │    │
│  │   │   150x150 px        │       │    │
│  │   │   with soft glow    │       │    │
│  │   └─────────────────────┘       │    │
│  │                                 │    │
│  │   Sarah Johnson                 │    │ (.appLargeTitle)
│  │   28 • Software Engineer        │    │ (.appBody, secondaryText)
│  │                                 │    │
│  │   ❤️ 85 Affinity                │    │ (.appHeadline, primary)
│  │   [████████░░] gradient         │    │ (8pt height)
│  │                                 │    │
│  │   💕 10 months together         │    │ (.appBody, accent)
│  │                                 │    │
│  └─────────────────────────────────┘    │
└─────────────────────────────────────────┘
```

**Visual Specifications:**

| Element | Specification |
|---------|--------------|
| Container | BaseCard wrapper |
| Background | `LinearGradient(colors: [Color.pink.opacity(0.15), Color.purple.opacity(0.1)], startPoint: .topLeading, endPoint: .bottomTrailing)` |
| Padding | AppSpacing.lg all sides |
| Avatar Size | 150x150 points |
| Avatar Shadow | `.shadow(color: AppColors.primary.opacity(0.3), radius: 20, x: 0, y: 8)` |
| Name Font | .appLargeTitle |
| Age/Occupation Font | .appBody |
| Affinity Label Font | .appHeadline |
| Affinity Bar Height | 8pt |
| Affinity Bar Colors | `LinearGradient(colors: [AppColors.error, AppColors.warning, AppColors.success], startPoint: .leading, endPoint: .trailing)` |
| Duration Font | .appBody |
| Duration Color | AppColors.accent |

**Duration Text Logic:**
```swift
private func durationText(from startDate: String) -> String {
    let months = calculateMonths(from: startDate)

    if months == 1 {
        return "💕 1 month together"
    } else if months < 12 {
        return "💕 \(months) months together"
    } else {
        let years = months / 12
        let remainingMonths = months % 12

        if remainingMonths == 0 {
            return years == 1 ? "💕 1 year together" : "💕 \(years) years together"
        } else {
            return "💕 \(years)y \(remainingMonths)m together"
        }
    }
}

private func calculateMonths(from dateString: String) -> Int {
    // Implementation: Parse date string and calculate months
    // For now, use relationship.eventsLog.count as proxy
    return 10 // Placeholder
}
```

**Affinity Bar:**
- Width fills container
- Height: 8pt
- Background: AppColors.secondaryText.opacity(0.2)
- Fill: Gradient from red (0%) → yellow (50%) → green (100%)
- Fill width: `geometry.size.width * min(CGFloat(partner.affinity) / 100.0, 1.0)`
- Corner radius: 4pt

---

### Component 2: QuickActionsBar

**Purpose:** Provide instant access to primary relationship actions in a cozy, pill-style layout.

**File:** `Features/Dating/Components/QuickActionsBar.swift`

**API:**
```swift
struct QuickActionsBar: View {
    let partner: Person
    let onDateTap: () -> Void
    let onGiftTap: () -> Void
    let onChatTap: () -> Void

    var body: some View
}
```

**Layout:**
```
┌─────────────────────────────────────────┐
│  HStack (centered, spacing: AppSpacing.md) │
│                                         │
│  ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│  │ 💌 Date  │ │ 🎁 Gift  │ │ 💬 Chat │ │
│  └──────────┘ └──────────┘ └─────────┘ │
│  pill button   pill button  pill button│
└─────────────────────────────────────────┘
```

**Pill Button Specifications:**

| Property | Value |
|----------|-------|
| Height | 44pt (standard iOS touch target) |
| Horizontal Padding | AppSpacing.md |
| Vertical Padding | AppSpacing.sm |
| Background | `AppColors.cardBackground` |
| Border | 1pt, AppColors.secondaryText.opacity(0.2) |
| Shadow | `.shadow(color: .black.opacity(0.05), radius: 4, x: 0, y: 2)` |
| Corner Radius | 22pt (half height for perfect pill) |
| Font | .appBody |
| Icon Size | 18pt |
| Haptic | .light on tap |

**Button Definitions:**

**Date Button:**
```swift
ActionPill(
    icon: "calendar.badge.clock",
    label: "Date",
    iconColor: AppColors.primary,
    action: onDateTap
)
```

**Gift Button:**
```swift
ActionPill(
    icon: "gift.fill",
    label: "Gift",
    iconColor: AppColors.accent,
    action: onGiftTap
)
```

**Chat Button:**
```swift
ActionPill(
    icon: "message.fill",
    label: "Chat",
    iconColor: AppColors.success,
    action: onChatTap
)
```

**Subcomponent: ActionPill**
```swift
private struct ActionPill: View {
    let icon: String
    let label: String
    let iconColor: Color
    let action: () -> Void

    var body: some View {
        Button(action: {
            hapticFeedback(style: .light)
            action()
        }) {
            HStack(spacing: AppSpacing.xs) {
                Image(systemName: icon)
                    .font(.system(size: 18))
                    .foregroundColor(iconColor)

                Text(label)
                    .font(.appBody)
                    .foregroundColor(AppColors.primaryText)
            }
            .padding(.horizontal, AppSpacing.md)
            .padding(.vertical, AppSpacing.sm)
            .frame(height: 44)
            .background(AppColors.cardBackground)
            .overlay(
                RoundedRectangle(cornerRadius: 22)
                    .stroke(AppColors.secondaryText.opacity(0.2), lineWidth: 1)
            )
            .cornerRadius(22)
            .shadow(color: .black.opacity(0.05), radius: 4, x: 0, y: 2)
        }
        .buttonStyle(SquishButtonStyle())
    }
}
```

---

### Component 3: RelationshipSnapshotCard

**Purpose:** Quick overview of key relationship metrics at a glance.

**File:** `Features/Dating/Components/RelationshipSnapshotCard.swift`

**API:**
```swift
struct RelationshipSnapshotCard: View {
    let relationship: Relationship
    let sharedInterestsCount: Int

    var body: some View
}
```

**Layout:**
```
┌─────────────────────────────────────────┐
│  BaseCard                               │
│  ┌─────────────────────────────────┐    │
│  │  HStack (evenly distributed)    │    │
│  │  ┌────────┐ ┌────────┐ ┌──────┐ │    │
│  │  │  ⭐    │ │  📅    │ │  🎯  │ │    │
│  │  │  87    │ │  10    │ │  3   │ │    │
│  │  │ Score  │ │ Months │ │Shared│ │    │
│  │  └────────┘ └────────┘ └──────┘ │    │
│  └─────────────────────────────────┘    │
└─────────────────────────────────────────┘
```

**Implementation:**

Reuses existing `StatBadge` component from `Features/Dating/Components/StatBadge.swift`:

```swift
struct RelationshipSnapshotCard: View {
    let relationship: Relationship
    let sharedInterestsCount: Int

    private var durationMonths: Int {
        calculateMonths(from: relationship.startDate)
    }

    var body: some View {
        BaseCard {
            VStack(spacing: AppSpacing.sm) {
                Text("Relationship Overview")
                    .font(.appHeadline)
                    .foregroundColor(AppColors.primaryText)

                Divider()
                    .background(AppColors.secondaryText.opacity(0.3))

                HStack(spacing: AppSpacing.md) {
                    StatBadge(
                        icon: "star.fill",
                        label: "Score",
                        value: relationship.relationshipScore,
                        color: AppColors.accent
                    )

                    StatBadge(
                        icon: "calendar.badge.clock",
                        label: durationLabel,
                        value: durationMonths,
                        color: AppColors.primary
                    )

                    StatBadge(
                        icon: "heart.circle.fill",
                        label: "Shared",
                        value: sharedInterestsCount,
                        color: AppColors.success
                    )
                }
            }
        }
    }

    private var durationLabel: String {
        if durationMonths < 12 {
            return durationMonths == 1 ? "Month" : "Months"
        } else {
            let years = durationMonths / 12
            return years == 1 ? "Year" : "Years"
        }
    }
}
```

**Visual Specifications:**
- Uses existing `StatBadge` component (already styled consistently)
- Card title: "Relationship Overview"
- Three stats: Score, Duration, Shared Interests
- Evenly distributed with HStack

---

### Component 4: RecentMomentsCard

**Purpose:** Show recent relationship timeline events to create emotional connection.

**File:** `Features/Dating/Components/RecentMomentsCard.swift`

**API:**
```swift
struct RecentMomentsCard: View {
    let events: [String]
    let onViewAllTap: () -> Void

    var body: some View
}
```

**Layout:**
```
┌─────────────────────────────────────────┐
│  BaseCard                               │
│  ┌─────────────────────────────────┐    │
│  │  Recent Moments                 │    │
│  │  ────────────────────           │    │
│  │                                 │    │
│  │  💐 Had a wonderful dinner      │    │
│  │     at the Italian restaurant   │    │
│  │                                 │    │
│  │  🎂 Celebrated 6 month          │    │
│  │     anniversary together        │    │
│  │                                 │    │
│  │  [View All Moments →]           │    │
│  │                                 │    │
│  └─────────────────────────────────┘    │
└─────────────────────────────────────────┘
```

**Implementation:**

```swift
struct RecentMomentsCard: View {
    let events: [String]
    let onViewAllTap: () -> Void

    var body: some View {
        BaseCard {
            VStack(alignment: .leading, spacing: AppSpacing.sm) {
                HStack {
                    Image(systemName: "clock.fill")
                        .foregroundColor(AppColors.accent)

                    Text("Recent Moments")
                        .font(.appHeadline)
                        .foregroundColor(AppColors.primaryText)
                }

                Divider()
                    .background(AppColors.secondaryText.opacity(0.3))

                if events.isEmpty {
                    Text("No moments yet. Start creating memories together!")
                        .font(.appBody)
                        .foregroundColor(AppColors.secondaryText)
                        .padding(.vertical, AppSpacing.sm)
                } else {
                    VStack(alignment: .leading, spacing: AppSpacing.md) {
                        ForEach(events.prefix(3), id: \.self) { event in
                            MomentRow(event: event)
                        }
                    }
                }

                Button(action: {
                    hapticFeedback(style: .light)
                    onViewAllTap()
                }) {
                    HStack {
                        Text("View All Moments")
                            .font(.appBody)
                            .foregroundColor(AppColors.primary)

                        Image(systemName: "arrow.right")
                            .font(.appCaption)
                            .foregroundColor(AppColors.primary)
                    }
                }
                .padding(.top, AppSpacing.xs)
            }
        }
    }
}

private struct MomentRow: View {
    let event: String

    var body: some View {
        HStack(alignment: .top, spacing: AppSpacing.sm) {
            Image(systemName: iconForEvent(event))
                .font(.system(size: AppSpacing.iconSizeSmall))
                .foregroundColor(AppColors.accent)
                .frame(width: 24)

            Text(event)
                .font(.appBody)
                .foregroundColor(AppColors.secondaryText)
                .fixedSize(horizontal: false, vertical: true)
        }
    }

    private func iconForEvent(_ event: String) -> String {
        let lowercased = event.lowercased()

        if lowercased.contains("date") || lowercased.contains("dinner") {
            return "fork.knife"
        }
        if lowercased.contains("gift") {
            return "gift.fill"
        }
        if lowercased.contains("anniversary") {
            return "sparkles"
        }
        if lowercased.contains("message") || lowercased.contains("chat") {
            return "message.fill"
        }
        if lowercased.contains("travel") || lowercased.contains("trip") {
            return "airplane"
        }

        return "heart.fill" // Default romantic icon
    }
}
```

**Visual Specifications:**

| Element | Specification |
|---------|--------------|
| Container | BaseCard |
| Header Icon | clock.fill, AppColors.accent |
| Title Font | .appHeadline |
| Max Events Shown | 3 (most recent) |
| Event Icon Size | 24x24pt |
| Event Font | .appBody |
| Event Color | AppColors.secondaryText |
| View All Button | AppColors.primary, with arrow icon |

---

## DatingView Refactored Structure

**File:** `Features/Dating/Views/DatingView.swift`

### Main Body Implementation

```swift
var body: some View {
    VStack {
        if let relationshipStatus = relationship?.relationshipStatus,
           !relationshipStatus.isEmpty,
           let partner = partner {
            // NEW ROMANTIC LAYOUT
            ScrollView {
                VStack(spacing: AppSpacing.lg) {
                    // 1. Hero Card - Partner Spotlight
                    RomanticHeroCard(
                        partner: partner,
                        relationship: relationship!
                    )

                    // 2. Quick Actions
                    QuickActionsBar(
                        partner: partner,
                        onDateTap: { showPopover = true },
                        onGiftTap: {
                            let message = ["type": "partnerGift", "message": partner.id]
                            webSocketService.sendMessage(message: message)
                        },
                        onChatTap: {
                            selectedCharacter = partner
                            isChatViewPresented = true
                        }
                    )

                    // 3. Snapshot Stats
                    RelationshipSnapshotCard(
                        relationship: relationship!,
                        sharedInterestsCount: relationship!.commonInterests.count
                    )

                    // 4. Recent Moments
                    if !relationship!.eventsLog.isEmpty {
                        RecentMomentsCard(
                            events: relationship!.eventsLog,
                            onViewAllTap: { showRelationshipDetail = true }
                        )
                    }

                    // 5. View Full Details Button
                    SecondaryButton(title: "View Full Relationship Details") {
                        showRelationshipDetail = true
                    }

                    // 6. Destructive Action (bottom, separated)
                    Button(action: { showBreakUpConfirmation = true }) {
                        Text(relationship!.relationshipStatus == "Married" ? "Divorce" : "Break Up")
                            .font(.appBody)
                            .foregroundColor(AppColors.error)
                    }
                    .padding(.top, AppSpacing.xl)
                }
                .padding(AppSpacing.md)
            }
            .background(AppColors.primaryBackground)
            .edgesIgnoringSafeArea(.bottom)

            // PRESERVED: All existing sheets and modals
            .sheet(isPresented: $showPopover) {
                DateActivitySelectionView(
                    partner: partner,
                    onActivitySelected: { activity in
                        let message = ["type": "dateNight", "message": activity.name]
                        webSocketService.sendMessage(message: message)
                        showPopover = false
                    }
                )
                .environmentObject(webSocketService)
            }
            .sheet(isPresented: $showDateMiniGame) {
                DateMiniGameView(
                    gameState: DateMiniGameState(
                        id: UUID().uuidString,
                        partnerId: partner.id,
                        partnerName: "\(partner.firstname) \(partner.lastname)",
                        activityId: "date_activity",
                        questions: []
                    ),
                    partner: partner
                )
                .environmentObject(webSocketService)
            }
            .sheet(isPresented: $showRelationshipDetail) {
                if let relationship = relationship {
                    RelationshipDetailView(relationshipId: relationship.id)
                        .environmentObject(webSocketService)
                }
            }
            .sheet(isPresented: $showBreakUpConfirmation) {
                if let relationship = relationship {
                    let isMarried = relationship.relationshipStatus == "Married"
                    VStack(spacing: AppSpacing.lg) {
                        Image(systemName: "heart.slash.fill")
                            .font(.system(size: 60))
                            .foregroundColor(.red)

                        Text(isMarried ? "Divorce?" : "Break Up?")
                            .font(.appTitle)
                            .foregroundColor(AppColors.primaryText)

                        Text(isMarried ? "Are you sure you want to end this marriage?" : "Are you sure you want to end this relationship?")
                            .font(.appBody)
                            .foregroundColor(AppColors.secondaryText)
                            .multilineTextAlignment(.center)
                            .padding(.horizontal, AppSpacing.lg)

                        HStack(spacing: AppSpacing.md) {
                            SecondaryButton(title: "Cancel") {
                                showBreakUpConfirmation = false
                            }

                            PrimaryButton(
                                title: isMarried ? "Divorce" : "Break Up",
                                action: {
                                    let messageType = isMarried ? "divorce" : "breakUp"
                                    let message = ["type": messageType, "message": partner.id]
                                    webSocketService.sendMessage(message: message)
                                    showBreakUpConfirmation = false
                                },
                                backgroundColor: .red
                            )
                        }
                        .padding(.horizontal, AppSpacing.lg)
                    }
                    .padding(AppSpacing.xl)
                }
            }
            .sheet(isPresented: $isChatViewPresented) {
                if let character = selectedCharacter {
                    ChatView(characterID: character.id)
                }
            }
        } else {
            // UNCHANGED: Single state view
            VStack {
                Text("You are not dating anyone.")
                    .font(.title)
                    .foregroundStyle(AppColors.primaryText)

                Button("Start Swiping!") {
                    isSwipeDatingViewPresented.toggle()
                }
                .padding(20)
                .sheet(isPresented: $isSwipeDatingViewPresented) {
                    SwipeDatingView()
                }

                if !webSocketService.player.r.contains(where: { $0.relationships.contains("dating_match") }) {
                    Text("You have no matches")
                        .foregroundColor(AppColors.primaryText)
                        .padding()
                }

                ScrollView {
                    ForEach(webSocketService.player.r) { person in
                        if person.relationships.contains("dating_match") {
                            Button(action: {
                                selectedCharacter = person
                                isChatViewPresented.toggle()
                            }) {
                                CharacterView(person: person)
                            }
                            .buttonStyle(PrimaryButtonStyle())
                            .frame(maxWidth: .infinity)
                        }
                    }
                }
                .sheet(isPresented: $isChatViewPresented, content: {
                    if let character = selectedCharacter {
                        ChatView(characterID: character.id)
                    }
                })
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(AppColors.primaryBackground)
                .edgesIgnoringSafeArea(.horizontal)
                .padding(.bottom, 100)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(AppColors.primaryBackground)
            .edgesIgnoringSafeArea(.all)
        }
    }
    .onAppear {
        AnalyticsManager.shared.trackScreenView("dating", screenClass: "DatingView")
    }
}
```

### Preserved State Variables

All existing @State variables remain unchanged:

```swift
@State private var isSwipeDatingViewPresented = false
@State private var isChatViewPresented: Bool = false
@State private var selectedCharacter: Person?
@State private var showPopover = false
@State private var showDateMiniGame = false
@State private var showRelationshipDetail = false
@State private var showBreakUpConfirmation = false
```

### Preserved Computed Properties

```swift
var relationship: Relationship? {
    let relationshipId = webSocketService.person.relationship
    return webSocketService.player.relData.first(where: { $0.id == relationshipId })
}

var partner: Person? {
    guard let partnerId = relationship?.person2 else {
        return nil
    }
    return webSocketService.player.r.first(where: { $0.id == partnerId })
}
```

---

## Visual Design System

### Color Palette

**Romantic Gradient Backgrounds:**
```swift
// Hero card gradient
LinearGradient(
    colors: [
        Color.pink.opacity(0.15),
        Color.purple.opacity(0.1)
    ],
    startPoint: .topLeading,
    endPoint: .bottomTrailing
)

// Affinity bar gradient (emotional scale)
LinearGradient(
    colors: [
        AppColors.error,      // Low affinity: red
        AppColors.warning,    // Medium: yellow/orange
        AppColors.success     // High affinity: green
    ],
    startPoint: .leading,
    endPoint: .trailing
)
```

**Primary Colors Used:**
- AppColors.primary - Main romantic accent (hearts, primary actions)
- AppColors.accent - Secondary romantic accent (sparkles, celebrations)
- AppColors.success - Positive indicators (high affinity, shared interests)
- AppColors.error - Negative/destructive actions (break up, low affinity)
- AppColors.warning - Cautionary indicators (medium affinity)

### Typography Scale

```swift
.appLargeTitle    // Partner name
.appTitle         // Section headers (preserved in modals)
.appHeadline      // Stat values, affinity label, card titles
.appBody          // Descriptions, event text, button labels
.appBodyBold      // Emphasized body text
.appCaption       // Secondary info (age, occupation)
.appSmall         // Stat labels
```

### Spacing System

```swift
AppSpacing.xs     // 4pt  - Tight spacing (icon-text)
AppSpacing.sm     // 8pt  - Small spacing (between elements)
AppSpacing.md     // 16pt - Medium spacing (card padding, between sections)
AppSpacing.lg     // 24pt - Large spacing (between major sections)
AppSpacing.xl     // 32pt - Extra large (top-level padding)
AppSpacing.xxl    // 48pt - Maximum spacing (unused in this design)
```

### Icon System

**Romantic/Relationship Icons:**
- `heart.fill` - General love/affection
- `heart.circle.fill` - Shared interests
- `sparkles` - Special moments, anniversaries
- `calendar.badge.clock` - Duration, scheduling
- `gift.fill` - Gifts
- `message.fill` - Messages/chat
- `fork.knife` - Date/dinner
- `star.fill` - Relationship score
- `clock.fill` - Recent moments/timeline
- `heart.slash.fill` - Break up (destructive)

### Shadows & Effects

```swift
// Hero card avatar glow
.shadow(color: AppColors.primary.opacity(0.3), radius: 20, x: 0, y: 8)

// Pill buttons subtle depth
.shadow(color: .black.opacity(0.05), radius: 4, x: 0, y: 2)

// Standard card shadow (from BaseCard)
// Inherited from existing design system
```

---

## Implementation Plan

### Phase 1: Create New Components (2-3 hours)

**Task 1.1: RomanticHeroCard**
- Create file: `Features/Dating/Components/RomanticHeroCard.swift`
- Implement gradient background
- Add partner avatar with glow effect
- Add affinity bar with gradient
- Add duration calculation logic
- Add preview with mock data

**Task 1.2: QuickActionsBar**
- Create file: `Features/Dating/Components/QuickActionsBar.swift`
- Implement ActionPill subcomponent
- Add three action buttons (Date, Gift, Chat)
- Add haptic feedback
- Add preview

**Task 1.3: RelationshipSnapshotCard**
- Create file: `Features/Dating/Components/RelationshipSnapshotCard.swift`
- Reuse StatBadge component
- Add three stats (Score, Duration, Shared)
- Add duration label logic
- Add preview

**Task 1.4: RecentMomentsCard**
- Create file: `Features/Dating/Components/RecentMomentsCard.swift`
- Implement MomentRow subcomponent
- Add event icon mapping logic
- Add "View All" button
- Add empty state
- Add preview

### Phase 2: Refactor DatingView (1-2 hours)

**Task 2.1: Update DatingView**
- Import new components
- Refactor in-relationship branch to use new layout
- Wire up action callbacks
- Preserve all existing sheets/modals
- Preserve all @State variables
- Test all navigation flows

**Task 2.2: Verify Functionality**
- Test date scheduling
- Test gift sending
- Test chat opening
- Test relationship detail navigation
- Test break up confirmation
- Verify analytics tracking still works

### Phase 3: Testing & Polish (1 hour)

**Task 3.1: Visual QA**
- Check all spacing consistency
- Verify color usage matches design system
- Test light/dark mode (if applicable)
- Check different relationship statuses (Dating, Engaged, Married)
- Test with different affinity levels
- Test with empty events log

**Task 3.2: Edge Cases**
- Very long partner names
- Very long event descriptions
- Zero shared interests
- Maximum affinity (100)
- Minimum affinity (0)
- Relationship duration edge cases (1 month, 12 months, 2 years, etc.)

**Task 3.3: Performance**
- Verify smooth scrolling
- Check for memory leaks in previews
- Ensure haptic feedback works correctly

---

## Success Metrics

**Qualitative:**
- Partner feels "front and center" visually
- Romantic/cozy aesthetic achieved
- Clear visual hierarchy
- Easy to understand and navigate
- Maintains consistency with app design system

**Quantitative:**
- Zero breaking changes to existing functionality
- All 4 new components have working previews
- DatingView code reduced from 320 lines to ~200 lines
- Component files average 100-150 lines each
- All existing analytics events still fire
- All WebSocket messages still send correctly

---

## Future Enhancements

These are out of scope for this redesign but noted for future consideration:

1. **Floating heart animation** on RomanticHeroCard
   - Subtle particle effect on hero card background
   - Uses CAEmitterLayer or SwiftUI animations

2. **Milestone badges** in RecentMomentsCard
   - Special badges for anniversaries, engagement, marriage
   - Confetti animation on milestone tap

3. **Affinity trend indicator**
   - Arrow showing affinity change over past week
   - Green up arrow or red down arrow next to affinity

4. **Quick date suggestions**
   - AI-powered date ideas based on shared interests
   - "Sarah loves hiking - try a nature walk!" hint card

5. **Relationship health score**
   - Overall health metric combining affinity, frequency of interaction, shared activities
   - Traffic light indicator (green/yellow/red)

6. **Partner bio section**
   - Add partner's bio (if available) to hero card
   - Expandable "Read more" for longer bios

---

## Dependencies

**Existing Components (Reused):**
- BaseCard
- StatBadge
- PrimaryButton
- SecondaryButton
- SVGImageView
- DateActivitySelectionView
- DateMiniGameView
- RelationshipDetailView
- ChatView

**Design System:**
- AppColors
- AppSpacing
- Typography (appLargeTitle, appHeadline, appBody, etc.)
- SquishButtonStyle (for buttons)

**Services:**
- WebSocketService (for all game state)
- AnalyticsManager (for tracking)
- SoundManager (optional, if adding sounds)
- HapticFeedback (for tactile feedback)

**Data Models:**
- Person
- Relationship

---

## Testing Strategy

### Unit Testing (Optional)

While SwiftUI views are typically tested visually via previews, we can add basic tests for logic:

```swift
// Test duration calculation
func testDurationText() {
    let card = RomanticHeroCard(partner: mockPartner, relationship: mockRelationship)
    // Test various date ranges
}

// Test event icon mapping
func testEventIconMapping() {
    let mapper = RecentMomentsCard.MomentRow(event: "Had dinner")
    XCTAssertEqual(mapper.iconForEvent("Had dinner"), "fork.knife")
}
```

### Visual Testing

**Preview-Driven Development:**
- Each component has SwiftUI preview with mock data
- Test various states in previews:
  - Different affinity levels (0, 50, 100)
  - Different relationship durations
  - Different event types
  - Empty states

**Manual Testing:**
- Test on various iPhone sizes (SE, 14, 14 Pro Max)
- Test in simulator and on device
- Verify haptic feedback on device

---

## Rollout Plan

### Development Workflow

1. Create feature branch: `feature/dating-view-romantic-redesign`
2. Implement components one-by-one with previews
3. Test each component in isolation
4. Refactor DatingView to use new components
5. Test full integration
6. Create PR with screenshots
7. QA review
8. Merge to main

### Risk Mitigation

**Risk:** Breaking existing functionality
- **Mitigation:** Only modify in-relationship branch, leave single state unchanged
- **Mitigation:** Preserve all @State variables and computed properties
- **Mitigation:** Manual testing checklist before PR

**Risk:** Visual inconsistency with rest of app
- **Mitigation:** Use existing design system exclusively
- **Mitigation:** Reuse existing components (BaseCard, StatBadge, etc.)
- **Mitigation:** Get design review before implementation

**Risk:** Performance issues with new layout
- **Mitigation:** Use LazyVStack if needed (currently not necessary)
- **Mitigation:** Test on older devices (iPhone 11)
- **Mitigation:** Profile with Instruments if issues arise

---

## Appendix A: Design Alternatives Considered

### Alternative 1: Integrated Dashboard Layout

**Why not chosen:** Less emotional impact, felt too clinical

**Pros:**
- All info visible at once
- Efficient use of space

**Cons:**
- Partner doesn't feel special
- Information overload
- Less romantic aesthetic

### Alternative 2: Story Card Stack Layout

**Why not chosen:** Too complex for initial implementation, longer development time

**Pros:**
- Most romantic/emotional
- Unique experience
- Great engagement

**Cons:**
- Requires more scrolling
- More complex to implement
- Could be overwhelming
- Higher development effort (6-8 hours vs 4-5 hours)

### Selected: Romance-First Hero Layout

**Why chosen:**
- Best balance of emotion and usability
- Leverages existing components
- Quick to implement
- Mobile-friendly
- Supports future enhancements

---

## Appendix B: Mock Data for Previews

```swift
// Mock Partner
let mockPartner: Person = {
    let person = Person()
    person.id = "partner123"
    person.firstname = "Sarah"
    person.lastname = "Johnson"
    person.ageYears = 28
    person.sex = "Female"
    person.occupation = "Software Engineer"
    person.image = "https://api.dicebear.com/7.x/avataaars/svg?seed=Sarah"
    person.affinity = 85
    return person
}()

// Mock Relationship
let mockRelationship = Relationship(
    id: "rel123",
    person1: "player123",
    person2: "partner123",
    startDate: "Jan 15, 2024",
    relationshipStatus: "Dating",
    relationshipNotes: "Met at a coffee shop",
    eventsLog: [
        "Had a wonderful dinner at the Italian restaurant",
        "Celebrated 6 month anniversary together",
        "Sent a thoughtful gift for her birthday",
        "Went hiking in the mountains",
        "Had our first argument but worked through it"
    ],
    relationshipScore: 87,
    commonInterests: ["music", "hiking", "cooking", "travel", "tech"],
    challenges: ["Long distance occasionally", "Different work schedules"],
    futurePlans: ["Move in together", "Travel to Europe", "Get a pet"]
)
```

---

## Conclusion

This redesign transforms the DatingView from a functional but emotionally flat interface into a romantic, cozy experience that puts the partner at center stage. By leveraging existing design system components and following established patterns, we achieve a significant visual upgrade with minimal development risk.

The modular component architecture ensures maintainability, testability, and sets the foundation for future enhancements like animations, milestone celebrations, and AI-powered relationship insights.

**Estimated total effort:** 4-5 hours
**Risk level:** Low (no breaking changes, uses existing patterns)
**Impact:** High (significant UX improvement, sets romantic tone for dating feature)
