Skip to content

Commit

Permalink
ScheduledTime
Browse files Browse the repository at this point in the history
  • Loading branch information
Supereg committed Jan 8, 2025
1 parent 29a6769 commit bef586d
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 120 deletions.
1 change: 0 additions & 1 deletion Sources/SpeziMedication/Medication/Medication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,4 @@ public struct MedicationDescription {
}

extension MedicationDescription: Codable, Equatable, Sendable {

}
11 changes: 7 additions & 4 deletions Sources/SpeziMedication/Schedule/Schedule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ public struct Schedule: Codable, Equatable, Hashable, Sendable {
/// The frequency of the Schedule, see ``Frequency`.`.
public var frequency: Frequency
/// The times of the Schedule, that are associated with the ``Schedule/frequency`.`.
public var times: [ScheduledTime]
public var times: [Date] // TODO: this is wrong now

Check failure on line 24 in Sources/SpeziMedication/Schedule/Schedule.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

Todo Violation: TODOs should be resolved (this is wrong now) (todo)
/// Start date of the schedule.
public var startDate: Date


/// - Parameters:
/// - frequency: The frequency of the Schedule, see ``Frequency`.`
/// - times: The times of the Schedule, that are associated with the ``Schedule/frequency`.`
public init(frequency: Frequency = .asNeeded, times: [ScheduledTime] = [], startDate: Date = .now) {
public init(frequency: Frequency = .asNeeded, times: [Date] = [], startDate: Date = .now) {
self.frequency = frequency
self.times = times
self.startDate = startDate
Expand All @@ -38,7 +38,7 @@ public struct Schedule: Codable, Equatable, Hashable, Sendable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.frequency = try container.decode(Frequency.self, forKey: .frequency)
self.times = try container.decodeIfPresent([ScheduledTime].self, forKey: .times) ?? []
self.times = try container.decodeIfPresent([Date].self, forKey: .times) ?? []
self.startDate = try container.decode(Date.self, forKey: .startDate)
}

Expand All @@ -64,14 +64,17 @@ public struct Schedule: Codable, Equatable, Hashable, Sendable {
case .asNeeded:
break
}


return times
/*
return times.compactMap { scheduledTime -> Date? in
guard let hour = scheduledTime.time.hour, let minute = scheduledTime.time.minute else {
return nil
}

return Calendar.current.date(bySettingHour: hour, minute: minute, second: 0, of: date)
}
*/
}

public func hash(into hasher: inout Hasher) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ struct AddMedicationSchedule: View {
@Environment(\.dismiss)
private var dismiss

@State private var frequency: Frequency = .regularDayIntervals(1)
@State private var startDate: Date = .now
@State private var times: [ScheduledTime] = []

@State private var viewModel = CreateScheduleViewModel() // TODO: integrate this new model!

@FocusState private var hasFocus: Bool
Expand All @@ -45,7 +41,7 @@ struct AddMedicationSchedule: View {
}
.headerProminence(.increased) // TODO: use that always?

EditScheduleTime(times: $times, model: $viewModel)
EditScheduleTime(model: $viewModel)
}
.focused($hasFocus)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct EditMedication<MI: MedicationInstance>: View {
@Environment(\.dismiss) private var dismiss
@Environment(InternalMedicationSettingsViewModel<MI>.self) private var viewModel

@Binding private var medicationInstance: MI
@Binding private var medicationInstance: MI // TODO: remove

// TODO: (e.g., $medicationInstance.schedule.frequency)
@State var model = CreateScheduleViewModel() // TODO: these needs to come from somewhere! and update it back
Expand All @@ -32,7 +32,7 @@ struct EditMedication<MI: MedicationInstance>: View {
EditFrequency(model: $model)
}
Section(String(localized: "Schedule Times", bundle: .module)) {
EditScheduleTime(times: $medicationInstance.schedule.times, model: $model)
EditScheduleTime(model: $model)
}
Section {
Button(String(localized: "Delete", bundle: .module), role: .destructive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,48 @@
// SPDX-License-Identifier: MIT
//

import SpeziMedication
import SwiftUI


struct EditScheduleTime: View {
// We assume that a user doesn't take a single medication more than the number of possible times which are 12 * 24 for 5 minute intervals.
private static let maxTimesCount = (60 / ScheduledTimeDatePicker.minuteInterval) * 24


@Binding private var times: [ScheduledTime]
@Binding private var model: CreateScheduleViewModel


var body: some View {
Section {
if case .weekdayBased = model.selection {
// TODO: disable days, if other day selection is already done.
WeekdaysPicker(selection: $model.weekdays)
}
if !model.times.isEmpty {
/*ForEach($model.times) { time in
}*/
}
if !times.isEmpty {
ForEach($times) { time in
// TODO: EditScheduleTimeRow(time: time, times: $times)
ForEach($model.times) { time in
EditScheduleTimeRow(time: time, form: nil) // TODO: propagate the form!
}
}
if times.count < Self.maxTimesCount {
addTimeButton
}
}
}

private var addTimeButton: some View {
Button(action: addNewTime) {
Label {
Text("Add a time", bundle: .module)
} icon: {
Image(systemName: "plus.circle.fill")
.accessibilityHidden(true)
.foregroundStyle(Color.green)
if model.times.count < Self.maxTimesCount {
Button(action: addNewTime) {
Label {
Text("Add a time", bundle: .module)
} icon: {
Image(systemName: "plus.circle.fill")
.accessibilityHidden(true)
.foregroundStyle(Color.green)
}
}
}
}
}


init(times: Binding<[ScheduledTime]>, model: Binding<CreateScheduleViewModel>) {
self._times = times
init(model: Binding<CreateScheduleViewModel>) {
self._model = model
}


private func addNewTime() {
private func addNewTime() { // TODO: move to model!
var endlessLoopCounter = 0
let possibleNewTime = times.last?.time.date?.addingTimeInterval(Double(ScheduledTimeDatePicker.minuteInterval) * 60) ?? Date.now
let possibleNewTime = model.times.last?.time.date?.addingTimeInterval(Double(ScheduledTimeDatePicker.minuteInterval) * 60) ?? Date.now
let possibleNewTimeMinute = Calendar.current.dateComponents([.minute], from: possibleNewTime)

guard var newTimeAdded = Calendar.current.date(
Expand All @@ -75,15 +61,15 @@ struct EditScheduleTime: View {
while endlessLoopCounter <= Self.maxTimesCount {
let newScheduleTime = ScheduledTime(date: newTimeAdded)

guard !times.contains(newScheduleTime) else {
guard !model.times.contains(newScheduleTime) else {
newTimeAdded.addTimeInterval(Double(ScheduledTimeDatePicker.minuteInterval) * 60)
endlessLoopCounter += 1
continue
}

withAnimation {
times.append(newScheduleTime)
times.sort()
model.times.append(newScheduleTime)
model.times.sort()
}
return
}
Expand All @@ -93,20 +79,18 @@ struct EditScheduleTime: View {

#if DEBUG
#Preview {
@Previewable @State var times: [ScheduledTime] = []
@Previewable @State var model = CreateScheduleViewModel()

List {
EditScheduleTime(times: $times, model: $model)
EditScheduleTime(model: $model)
}
}

#Preview {
@Previewable @State var times: [ScheduledTime] = []
@Previewable @State var model = CreateScheduleViewModel(selection: .weekdayBased)

List {
EditScheduleTime(times: $times, model: $model)
EditScheduleTime(model: $model)
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,12 @@ import SpeziMedication
import SwiftUI


struct ScheduleDosage { // TODO: Move to main
var time: Date
var quantity: Double // TODO: we really want a 10 base number here? (only 2 digits) (only 5,2 digits)
}


struct EditScheduleTimeRow: View {
private let form: MedicationType?

@Binding private var scheduledDosage: ScheduleDosage

@Binding private var scheduledDosage: ScheduledTime

// TODO: we really want a 10 base number here? (only 2 digits) (only 5,2 digits)
private let numberOfDosageFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
Expand All @@ -39,13 +34,14 @@ struct EditScheduleTimeRow: View {
}
.buttonStyle(.borderless)

ScheduledTimeDatePicker(date: $scheduledDosage.time.animation(), excludedDates: [])
// TODO: ways that a date already?
ScheduledTimeDatePicker(date: $scheduledDosage.date.animation(), excludedDates: [])
.frame(maxWidth: 70)
// TODO: excluded: times.map(\.date)

Spacer()

TextField(value: $scheduledDosage.quantity, formatter: numberOfDosageFormatter) {
TextField(value: $scheduledDosage.dosage, formatter: numberOfDosageFormatter) {
Text("Quantity", bundle: .module)
}
.textFieldStyle(.roundedBorder)
Expand All @@ -66,19 +62,19 @@ struct EditScheduleTimeRow: View {
}
}

init(scheduledDosage: Binding<ScheduleDosage>, form: MedicationType?) {
init(time: Binding<ScheduledTime>, form: MedicationType?) {
self.form = form
self._scheduledDosage = scheduledDosage
self._scheduledDosage = time
}
}


#if DEBUG
#Preview {
@Previewable @State var time = ScheduleDosage(time: .now, quantity: 1.0)
@Previewable @State var time = ScheduledTime(date: .now, dosage: 1.0)

List {
EditScheduleTimeRow(scheduledDosage: $time, form: .tablet)
EditScheduleTimeRow(time: $time, form: .tablet)
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public struct CreateScheduleViewModel {
/// This value only applies if ``selection`` is equal to ``ScheduleFrequencySelection/weekdayBased``.
public var weekdays: Set<Locale.Weekday> = []
/// The timestamps that are selected.
public var times: [Date] = []
public var times: [ScheduledTime] = []

/// The start date of the schedule.
public var start: Date
Expand All @@ -48,9 +48,9 @@ public struct CreateScheduleViewModel {
} ?? .never


let (hours, minutes) = times.reduce(into: ([Int](), [Int]())) { partialResult, date in
partialResult.0.append(Calendar.current.component(.hour, from: date))
partialResult.1.append(Calendar.current.component(.minute, from: date))
let (hours, minutes) = times.reduce(into: ([Int](), [Int]())) { partialResult, scheduledTime in
partialResult.0.append(Calendar.current.component(.hour, from: scheduledTime.date))
partialResult.1.append(Calendar.current.component(.minute, from: scheduledTime.date))
}

let interval = if case .interval = selection {
Expand Down Expand Up @@ -101,7 +101,7 @@ public struct CreateScheduleViewModel {

self.selection = selection
self.dayInterval = dayInterval
self.times = [now] // default selected time is now
self.times = [ScheduledTime(date: now, dosage: 1)] // default selected time is now
self.weekdays = [todayWeekday] // default selected weekday is today
self.start = start
self.end = end
Expand Down
Loading

0 comments on commit bef586d

Please sign in to comment.