From 2608b352deecbe96c8c30c68a90f4c9337558d80 Mon Sep 17 00:00:00 2001 From: oliverhnat Date: Sat, 6 Jan 2024 20:52:51 +0100 Subject: [PATCH] Created card UI and added sleep debt functionality, still needs some polishing --- SleepDebt.xcodeproj/project.pbxproj | 4 ++ SleepDebt/CardView.swift | 74 +++++++++++++++++++++++++++++ SleepDebt/HomeView.swift | 30 +++++++++--- SleepDebt/SettingsView.swift | 2 +- SleepDebt/SleepDebtApp.swift | 2 + 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 SleepDebt/CardView.swift diff --git a/SleepDebt.xcodeproj/project.pbxproj b/SleepDebt.xcodeproj/project.pbxproj index 62b1229..8f7de09 100644 --- a/SleepDebt.xcodeproj/project.pbxproj +++ b/SleepDebt.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 6CD7B4BB2B49AA5100D1D8B8 /* SleepDebtTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD7B4BA2B49AA5100D1D8B8 /* SleepDebtTabView.swift */; }; 6CD7B4BD2B49AB3F00D1D8B8 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD7B4BC2B49AB3F00D1D8B8 /* SettingsView.swift */; }; 6CD7B4C12B49C45400D1D8B8 /* SettingsNumberFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD7B4C02B49C45400D1D8B8 /* SettingsNumberFieldView.swift */; }; + 6CD7B4C52B49D3BB00D1D8B8 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD7B4C42B49D3BB00D1D8B8 /* CardView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -28,6 +29,7 @@ 6CD7B4BA2B49AA5100D1D8B8 /* SleepDebtTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SleepDebtTabView.swift; sourceTree = ""; }; 6CD7B4BC2B49AB3F00D1D8B8 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 6CD7B4C02B49C45400D1D8B8 /* SettingsNumberFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsNumberFieldView.swift; sourceTree = ""; }; + 6CD7B4C42B49D3BB00D1D8B8 /* CardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +66,7 @@ 6C560B842B495DED00FDB70C /* SleepDebtApp.swift */, 6C560B862B495DED00FDB70C /* HomeView.swift */, 6CD7B4BA2B49AA5100D1D8B8 /* SleepDebtTabView.swift */, + 6CD7B4C42B49D3BB00D1D8B8 /* CardView.swift */, 6CD7B4BC2B49AB3F00D1D8B8 /* SettingsView.swift */, 6CD7B4C02B49C45400D1D8B8 /* SettingsNumberFieldView.swift */, 6C560B922B495E3A00FDB70C /* HealthKitManager.swift */, @@ -151,6 +154,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6CD7B4C52B49D3BB00D1D8B8 /* CardView.swift in Sources */, 6C560B872B495DED00FDB70C /* HomeView.swift in Sources */, 6CD7B4C12B49C45400D1D8B8 /* SettingsNumberFieldView.swift in Sources */, 6CD7B4BB2B49AA5100D1D8B8 /* SleepDebtTabView.swift in Sources */, diff --git a/SleepDebt/CardView.swift b/SleepDebt/CardView.swift new file mode 100644 index 0000000..df2a91b --- /dev/null +++ b/SleepDebt/CardView.swift @@ -0,0 +1,74 @@ +// +// CardView.swift +// SleepDebt +// +// Created by Oliver Hnát on 06.01.2024. +// + +import SwiftUI + +extension Int { + var toHoursMinuteString: String { + return "\(self / 60 / 60)h \(self / 60 % 60)m" + + } + +} + +extension Color { + init(hex: String) { + var cleanHexCode = hex.trimmingCharacters(in: .whitespacesAndNewlines) + cleanHexCode = cleanHexCode.replacingOccurrences(of: "#", with: "") + var rgb: UInt64 = 0 + + Scanner(string: cleanHexCode).scanHexInt64(&rgb) + + let redValue = Double((rgb >> 16) & 0xFF) / 255.0 + let greenValue = Double((rgb >> 8) & 0xFF) / 255.0 + let blueValue = Double(rgb & 0xFF) / 255.0 + self.init(red: redValue, green: greenValue, blue: blueValue) + } +} + +struct CardView: View { + var topText: String + var value: Int + var image: String + var bottomText: String? + var body: some View { + ZStack { + Color.init(hex: "#0b1d2e") + .cornerRadius(20) + .scaledToFill() + VStack { + VStack { + Image(systemName: image) + .font(.title) + Text(topText) + .font(.title3) + .padding() + .multilineTextAlignment(.center) + } + .multilineTextAlignment(.leading) + Text(value.toHoursMinuteString) + .font(.largeTitle) + .padding() + .multilineTextAlignment(.center) + if (bottomText != nil) { + Text(bottomText ?? "You're not supposed to see this") + .font(.title3) + .padding(.horizontal) + .multilineTextAlignment(.center) + + } + } + } + } +} + +#Preview { + VStack { + CardView(topText: "Your sleep debt for the last 7 days is", value: 876750 - 8 * 30 * 60 * 60, image: "moon.zzz") // sleep debt of ~15.5h + CardView(topText: "You should sleep at least", value: 8 * 60 * 60 - 876750 / 30 , image: "moon.zzz.fill", bottomText: "per day to catch up on your sleep in 7 days") + } +} diff --git a/SleepDebt/HomeView.swift b/SleepDebt/HomeView.swift index bfcb862..40e5b93 100644 --- a/SleepDebt/HomeView.swift +++ b/SleepDebt/HomeView.swift @@ -10,13 +10,19 @@ import SwiftUI struct HomeView: View { @EnvironmentObject var manager: HealthKitManager @EnvironmentObject var settings: SleepDebtSettings - var desiredAmountOfSleep = 8 var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundStyle(.tint) - Text(String(manager.sleepForLastXDays[settings.sleepDebtPeriod] ?? 0)) + ZStack { + LazyHGrid(rows: Array(repeating: GridItem(spacing: 20), count: 2)) { + CardView( + topText: "Your sleep debt for the last \(settings.sleepDebtPeriod.rawValue) days is", + value: self.getTotalSleepDebt(), + image: "moon.zzz") + CardView(topText: "You should sleep at least", + value: self.getDailyRepaymentSleep(), + image: "moon.zzz.fill", + bottomText: "per day to catch up on your sleep in \(settings.repaymentPeriod) days") + } + .padding(.horizontal) } .padding() .onAppear { @@ -26,10 +32,22 @@ struct HomeView: View { manager.updateSleep() }) } + + private func getTotalSleepDebt() -> Int { + let totalSleep = manager.sleepForLastXDays[settings.sleepDebtPeriod] ?? 0 + let desiredSleep = settings.desiredHoursOfSleep * settings.sleepDebtPeriod.rawValue * 60 * 60 + return max(desiredSleep - totalSleep, 0) + } + + private func getDailyRepaymentSleep() -> Int { + let sleepDebtPerDay = self.getTotalSleepDebt() / settings.repaymentPeriod + return settings.desiredHoursOfSleep * 60 * 60 + sleepDebtPerDay + } } #Preview { HomeView() .environmentObject(HealthKitManager()) .environmentObject(SleepDebtSettings()) + } diff --git a/SleepDebt/SettingsView.swift b/SleepDebt/SettingsView.swift index 8c2e3df..a31df3f 100644 --- a/SleepDebt/SettingsView.swift +++ b/SleepDebt/SettingsView.swift @@ -12,7 +12,7 @@ struct SettingsView: View { @FocusState private var focusItem: Bool private var repaymentString = "Repayment period (days)" private var sleepDebtString = "Sleep debt period (days)" - private var desiredHoursOfSleepString = "Desired hours of sleep" + private var desiredHoursOfSleepString = "Desired hours of sleep per day" var body: some View { NavigationStack { diff --git a/SleepDebt/SleepDebtApp.swift b/SleepDebt/SleepDebtApp.swift index 2f69c3a..c4f259e 100644 --- a/SleepDebt/SleepDebtApp.swift +++ b/SleepDebt/SleepDebtApp.swift @@ -16,6 +16,8 @@ struct SleepDebtApp: App { SleepDebtTabView() .environmentObject(healthKitManager) .environmentObject(settings) + .preferredColorScheme(.dark) + } } }