Andreas Stokholm 1 год назад
Родитель
Сommit
2aae4d0eb6

+ 60 - 0
FreeAPS/Sources/Modules/CarbRatioEditor/View/CarbRatioEditorRootView.swift

@@ -1,3 +1,4 @@
+import Charts
 import SwiftUI
 import Swinject
 
@@ -154,6 +155,7 @@ extension CarbRatioEditor {
 
         private var list: some View {
             List {
+                chart.padding(.vertical)
                 ForEach(state.items.indexed(), id: \.1.id) { index, item in
                     NavigationLink(destination: pickers(for: index)) {
                         HStack {
@@ -174,6 +176,64 @@ extension CarbRatioEditor {
             }
         }
 
+        let chartScale = Calendar.current
+            .date(from: DateComponents(year: 2001, month: 01, day: 01, hour: 0, minute: 0, second: 0))
+
+        var chart: some View {
+            Chart {
+                ForEach(state.items.indexed(), id: \.1.id) { index, item in
+                    let displayValue = state.rateValues[item.rateIndex]
+
+                    let tzOffset = TimeZone.current.secondsFromGMT() * -1
+                    let startDate = Date(timeIntervalSinceReferenceDate: state.timeValues[item.timeIndex])
+                        .addingTimeInterval(TimeInterval(tzOffset))
+                    let endDate = state.items
+                        .count > index + 1 ?
+                        Date(timeIntervalSinceReferenceDate: state.timeValues[state.items[index + 1].timeIndex])
+                        .addingTimeInterval(TimeInterval(tzOffset)) :
+                        Date(timeIntervalSinceReferenceDate: state.timeValues.last!).addingTimeInterval(30 * 60)
+                        .addingTimeInterval(TimeInterval(tzOffset))
+                    RectangleMark(
+                        xStart: .value("start", startDate),
+                        xEnd: .value("end", endDate),
+                        yStart: .value("rate-start", displayValue),
+                        yEnd: .value("rate-end", 0)
+                    ).foregroundStyle(
+                        .linearGradient(
+                            colors: [
+                                Color.orange.opacity(0.6),
+                                Color.orange.opacity(0.1)
+                            ],
+                            startPoint: .bottom,
+                            endPoint: .top
+                        )
+                    ).alignsMarkStylesWithPlotArea()
+
+                    LineMark(x: .value("End Date", startDate), y: .value("Amount", displayValue))
+                        .lineStyle(.init(lineWidth: 1)).foregroundStyle(Color.orange)
+
+                    LineMark(x: .value("Start Date", endDate), y: .value("Amount", displayValue))
+                        .lineStyle(.init(lineWidth: 1)).foregroundStyle(Color.orange)
+                }
+            }
+            .chartXAxis {
+                AxisMarks(values: .automatic(desiredCount: 6)) { _ in
+                    AxisValueLabel(format: .dateTime.hour())
+                    AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1, dash: [2, 4]))
+                }
+            }
+            .chartXScale(
+                domain: Calendar.current.startOfDay(for: chartScale!) ... Calendar.current.startOfDay(for: chartScale!)
+                    .addingTimeInterval(60 * 60 * 24)
+            )
+            .chartYAxis {
+                AxisMarks(values: .automatic(desiredCount: 4)) { _ in
+                    AxisValueLabel()
+                    AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1, dash: [2, 4]))
+                }
+            }
+        }
+
         private var addButton: some View {
             guard state.canAdd else {
                 return AnyView(EmptyView())