← Back to portfolio
😎💧 AquaVibe

😎💧 AquaVibe

Track your wellness journey with AquaVibe, your all-in-one companion for mood, emotion, and hydration tracking 😊💦

The application allows users to set up to 3 daily reminders for consistent tracking and visualize their well-being with beautiful, interactive charts 📈

👨‍💻 Technology Used

  • SwiftUI
  • HealthKit
  • Charts
  • UserNotifications
  • WishKit
  • StoreKit2, RevenueCat
  • TelemetryDeck
  • AVKit, AVFoundation

📌 What Changed In The Repo

Biggest evolution was shipping AquaVibe from zero to production app during RevenueCat Ship-a-ton, and implementing reliable State of Mind fetching/saving with HealthKit for iOS 18+.

🎥 AquaVibe In Action

AquaVibe demo video

🏆 Standout Success

AquaVibe was created from scratch to a fully working iOS application during RevenueCat Ship-a-ton competition.

AquaVibe won a Participation Prize in RevenueCat Ship-a-ton competition.

The most challenging part was understanding State of Mind logic. Documentation and sample projects were not enough, so extensive testing was needed to verify how to correctly fetch and save mood/emotion data to Apple HealthKit.

State of Mind is also new from iOS 18, so high-quality implementation references were limited.

func fetchStateOfMindData(forKind kind: HKStateOfMind.Kind) async throws -> [HKStateOfMind] {
        do {
            let stateOfMindType = HKSampleType.stateOfMindType()
            
            // Create a predicate for the specified kind
            let kindPredicate = HKQuery.predicateForStatesOfMind(with: kind)
            
            // Combine with the sample type predicate
            let combinedPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
                HKQuery.predicateForSamples(withStart: nil, end: nil, options: .strictStartDate),
                kindPredicate
            ])
            
            let descriptor = HKSampleQueryDescriptor(
                predicates: [.sample(type: stateOfMindType, predicate: combinedPredicate)],
                sortDescriptors: [SortDescriptor(\.startDate, order: .reverse)]
            )
            
            let samples = try await descriptor.result(for: store)
            
            if let stateOfMindSamples = samples as? [HKStateOfMind] {
                print("✅ Fetch done for \(kind)")
                print("Number of samples: \(stateOfMindSamples.count)")
                return stateOfMindSamples
            } else {
                print("❌ No HKStateOfMind samples found for \(kind)")
                return []
            }
        } catch {
            print("❌ Error fetching state of mind data for \(kind): \(error.localizedDescription)")
            return []
        }
    }
AquaVibe app screenshot
AquaVibe UI preview

✅ Entireness

Nevertheless, while creating this mood and water intake reminder app, I have also included:

  • Concurrency
  • Error handling & alerts
  • Text input validation
  • Project organization - MVVM Architecture
  • Published in App Store (09/2024)

ℹ️ License

The AquaVibe is the property of Marcin Jędrzejak. Unauthorized copying, distribution, or modification of this application is strictly prohibited.