Skip to content

Commit

Permalink
Added initial data models
Browse files Browse the repository at this point in the history
  • Loading branch information
Calvin-Xu committed Jan 31, 2025
1 parent 66bb8c1 commit 7288bf0
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 7 deletions.
22 changes: 15 additions & 7 deletions Feedbridge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 63;
objectVersion = 70;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -133,6 +133,10 @@
A9FE7ACF2AA39BAB0077B045 /* AccountSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSheet.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedRootGroup section */
5B4B0E102D4C5DBF0023EAB7 /* Models */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Models; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */

/* Begin PBXFrameworksBuildPhase section */
653A254A283387FE005D4D48 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
Expand Down Expand Up @@ -276,6 +280,7 @@
653A254F283387FE005D4D48 /* Feedbridge */ = {
isa = PBXGroup;
children = (
5B4B0E102D4C5DBF0023EAB7 /* Models */,
2FC975A72978F11A00BA99FE /* HomeView.swift */,
653A2550283387FE005D4D48 /* Feedbridge.swift */,
2F5E32BC297E05EA003432F8 /* FeedbridgeDelegate.swift */,
Expand Down Expand Up @@ -354,6 +359,9 @@
A9E1D3432C67A3F800CED217 /* PBXTargetDependency */,
56E7083D2BB06FCA00B08F0A /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
5B4B0E102D4C5DBF0023EAB7 /* Models */,
);
name = Feedbridge;
packageProductDependencies = (
2F49B7752980407B00BCB272 /* Spezi */,
Expand Down Expand Up @@ -693,11 +701,11 @@
INFOPLIST_KEY_NSMicrophoneUsageDescription = "This message should never appear. Please adjust this when you start using microphone information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_NSMotionUsageDescription = "This message should never appear. Please adjust this when you start using motion information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_NSSpeechRecognitionUsageDescription = "This message should never appear. Please adjust this when you start using speecg information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_UIFeedbridgelicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIFeedbridgelicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIFeedbridgelicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIFeedbridgelicationSupportsIndirectInputEvents = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down Expand Up @@ -897,11 +905,11 @@
INFOPLIST_KEY_NSMicrophoneUsageDescription = "This message should never appear. Please adjust this when you start using microphone information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_NSMotionUsageDescription = "This message should never appear. Please adjust this when you start using motion information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_NSSpeechRecognitionUsageDescription = "This message should never appear. Please adjust this when you start using speecg information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_UIFeedbridgelicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIFeedbridgelicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIFeedbridgelicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIFeedbridgelicationSupportsIndirectInputEvents = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down Expand Up @@ -944,11 +952,11 @@
INFOPLIST_KEY_NSMicrophoneUsageDescription = "This message should never appear. Please adjust this when you start using microphone information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_NSMotionUsageDescription = "This message should never appear. Please adjust this when you start using motion information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_NSSpeechRecognitionUsageDescription = "This message should never appear. Please adjust this when you start using speecg information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect.";
INFOPLIST_KEY_UIFeedbridgelicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIFeedbridgelicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIFeedbridgelicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIFeedbridgelicationSupportsIndirectInputEvents = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down
1 change: 1 addition & 0 deletions Feedbridge/.swift-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.0.3
67 changes: 67 additions & 0 deletions Feedbridge/Models/Baby.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// Baby.swift
// Feedbridge
//
// Created by Calvin Xu on 1/30/25.
//
import Foundation

/// Represents a baby and their associated health tracking data
struct Baby: Identifiable, Codable {

Check warning on line 10 in Feedbridge/Models/Baby.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Struct 'Baby' is unused
/// Unique identifier for the baby
var id: String = UUID().uuidString

/// Baby's full name
var name: String

/// Baby's date of birth
var dateOfBirth: Date

/// Collection of all feeding records
var feedEntries: [FeedEntry]

/// Collection of all weight measurements
var weightEntries: [WeightEntry]

/// Collection of all stool records
var stoolEntries: [StoolEntry]

/// Collection of all wet diaper records
var wetDiaperEntries: [WetDiaperEntry]

/// Collection of all dehydration check records
var dehydrationChecks: [DehydrationCheck]

/// Calculate baby's age in months (rounded down)
var ageInMonths: Int {
Calendar.current.dateComponents([.month], from: dateOfBirth, to: Date()).month ?? 0
}

/// Get the most recent weight entry
var currentWeight: WeightEntry? {
weightEntries.max(by: { $0.dateTime < $1.dateTime })
}

/// Get the most recent dehydration check
var latestDehydrationCheck: DehydrationCheck? {
dehydrationChecks.max(by: { $0.dateTime < $1.dateTime })
}

/// Check if there are any active medical alerts
var hasActiveAlerts: Bool {
latestDehydrationCheck?.dehydrationAlert == true ||
wetDiaperEntries.last?.dehydrationAlert == true ||
stoolEntries.last?.medicalAlert == true
}

/// Initialize a new baby with required information
init(name: String, dateOfBirth: Date) {
self.name = name
self.dateOfBirth = dateOfBirth
self.feedEntries = []
self.weightEntries = []
self.stoolEntries = []
self.wetDiaperEntries = []
self.dehydrationChecks = []
}
}
26 changes: 26 additions & 0 deletions Feedbridge/Models/DehydrationCheck.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// DehydrationCheck.swift
// Feedbridge
//
// Created by Calvin Xu on 1/30/25.
//
import Foundation

/// Stores dehydration-related information
struct DehydrationCheck: Identifiable, Codable {

Check warning on line 10 in Feedbridge/Models/DehydrationCheck.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Struct 'DehydrationCheck' is unused
var id: String = UUID().uuidString

/// Date and time of the check
var dateTime: Date

/// True if skin elasticity is reduced (e.g., "tenting" over abdomen)
var poorSkinElasticity: Bool

/// True if lips or tongue are dry
var dryMucousMembranes: Bool

/// Whether a medical alert has been triggered
var dehydrationAlert: Bool {
poorSkinElasticity || dryMucousMembranes
}
}
58 changes: 58 additions & 0 deletions Feedbridge/Models/FeedEntry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// FeedEntry.swift
// Feedbridge
//
// Created by Calvin Xu on 1/30/25.
//
import Foundation

/// Represents method of feeding
enum FeedType: String, Codable {

Check warning on line 10 in Feedbridge/Models/FeedEntry.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Enum 'FeedType' is unused
case directBreastfeeding
case bottle
}

/// Represents the type of milk used
enum MilkType: String, Codable {

Check warning on line 16 in Feedbridge/Models/FeedEntry.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Enum 'MilkType' is unused
case breastmilk
case formula
}

/// Stores feeding-related data
struct FeedEntry: Identifiable, Codable {

Check warning on line 22 in Feedbridge/Models/FeedEntry.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Struct 'FeedEntry' is unused
/// Use UUID to generate a unique identifier for Firebase
var id: String = UUID().uuidString

/// Date and time of the feed
var dateTime: Date

/// Type of feeding (direct breastfeeding or bottle)
var feedType: FeedType

/// Type of milk used if feedType = .bottle
var milkType: MilkType?

/// Duration of direct breastfeeding in minutes
var feedTimeInMinutes: Int?

/// Bottle feed volume in milliliters
var feedVolumeInML: Double?

/// Initialize for direct breastfeeding
init(directBreastfeeding minutes: Int, dateTime: Date = Date()) {
self.dateTime = dateTime
self.feedType = .directBreastfeeding
self.feedTimeInMinutes = minutes
self.milkType = nil
self.feedVolumeInML = nil
}

/// Initialize for bottle feeding
init(bottle volumeML: Double, milkType: MilkType, dateTime: Date = Date()) {
self.dateTime = dateTime
self.feedType = .bottle
self.milkType = milkType
self.feedVolumeInML = volumeML
self.feedTimeInMinutes = nil
}
}
48 changes: 48 additions & 0 deletions Feedbridge/Models/Guardian.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Guardian.swift
// Feedbridge
//
// Created by Calvin Xu on 1/30/25.
//
import Foundation

/// Represents a guardian (parent or caregiver) who takes care of babies
struct Guardian: Identifiable, Codable {

Check warning on line 10 in Feedbridge/Models/Guardian.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Struct 'Guardian' is unused
/// Unique identifier for the guardian
var id: String = UUID().uuidString

/// Guardian's full name
var name: String

/// Guardian's email address
var email: String

/// Guardian's phone number
var phoneNumber: String

/// Collection of babies under this guardian's care
var babies: [Baby]

/// Get all babies with active medical alerts
var babiesWithAlerts: [Baby] {
babies.filter { $0.hasActiveAlerts }
}

/// Initialize a new guardian with required information
init(name: String, email: String, phoneNumber: String) {
self.name = name
self.email = email
self.phoneNumber = phoneNumber
self.babies = []
}

/// Add a baby to the guardian's care
mutating func addBaby(_ baby: Baby) {
babies.append(baby)
}

/// Remove a baby from the guardian's care
mutating func removeBaby(withId id: String) {
babies.removeAll { $0.id == id }
}
}
43 changes: 43 additions & 0 deletions Feedbridge/Models/StoolEntry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// StoolEntry.swift
// Feedbridge
//
// Created by Calvin Xu on 1/30/25.
//
import Foundation

/// Represents stool volume classifications
enum StoolVolume: String, Codable {
case light
case medium
case heavy
}

/// Represents color variations for stool entries
enum StoolColor: String, Codable {
case black
case darkGreen
case green
case brown
case yellow
case beige
}

/// Stores stool data
struct StoolEntry: Identifiable, Codable {

Check warning on line 27 in Feedbridge/Models/StoolEntry.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Struct 'StoolEntry' is unused
var id: String = UUID().uuidString

/// Date and time of the stool event
var dateTime: Date

/// Volume classification
var volume: StoolVolume

/// Color of the stool
var color: StoolColor

/// Whether a medical alert should be displayed
var medicalAlert: Bool {
color == .beige
}
}
44 changes: 44 additions & 0 deletions Feedbridge/Models/WeightEntry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// WeightEntry.swift
// Feedbridge
//
// Created by Calvin Xu on 1/30/25.
//
import Foundation

/// Stores weight measurements (accepts grams, kilograms, or pounds and ounces)
struct WeightEntry: Identifiable, Codable {

Check warning on line 10 in Feedbridge/Models/WeightEntry.swift

View workflow job for this annotation

GitHub Actions / Periphery / Periphery

unused

Struct 'WeightEntry' is unused
var id: String = UUID().uuidString

/// Date and time the weight was measured
var dateTime: Date

/// Weight in grams (primary storage)
var weightInGrams: Double

var asKilograms: Measurement<UnitMass> {
Measurement(value: weightInGrams, unit: UnitMass.grams).converted(to: .kilograms)
}

var asPounds: Measurement<UnitMass> {
Measurement(value: weightInGrams, unit: UnitMass.grams).converted(to: .pounds)
}

init(grams: Double, dateTime: Date = Date()) {
self.dateTime = dateTime
self.weightInGrams = grams
}

init(kilograms: Double, dateTime: Date = Date()) {
let measurement = Measurement(value: kilograms, unit: UnitMass.kilograms)
self.dateTime = dateTime
self.weightInGrams = measurement.converted(to: .grams).value
}

init(pounds: Double, ounces: Double = 0, dateTime: Date = Date()) {
let totalPounds = pounds + (ounces / 16.0)
let measurement = Measurement(value: totalPounds, unit: UnitMass.pounds)
self.dateTime = dateTime
self.weightInGrams = measurement.converted(to: .grams).value
}
}
Loading

0 comments on commit 7288bf0

Please sign in to comment.