@@ -15,8 +15,10 @@ struct StepChartDataPoint: Identifiable {
1515}
1616
1717struct StepChartView : View {
18+ @ObservedObject var bleManager = BLEManager . shared
1819 @ObservedObject var chartManager = ChartManager . shared
1920 @ObservedObject var deviceManager = DeviceManager . shared
21+ @ObservedObject var stepCountManager = StepCountManager . shared
2022
2123 @AppStorage ( " stepChartDataSelection " ) var stepChartDataSelection = 0
2224
@@ -25,7 +27,7 @@ struct StepChartView: View {
2527 @State private var selectedDate = Date ( )
2628 @State private var selectedSteps = 0
2729
28- func data ( ) -> [ StepChartDataPoint ] {
30+ func weekSteps ( ) -> [ StepChartDataPoint ] {
2931 let calendar = Calendar . current
3032 let now = Date ( )
3133
@@ -54,51 +56,23 @@ struct StepChartView: View {
5456 return filledData
5557 }
5658
57- func header( ) -> some View {
58- VStack ( alignment: . leading) {
59- Text ( data ( ) . count > 1 ? showSelectionBar ? " Total " : " Average " : " " )
60- Text ( {
61- if showSelectionBar {
62- return " \( selectedSteps) "
63- } else if !data( ) . isEmpty {
64- return " \( data ( ) . reduce ( 0 ) { $0 + $1. steps } ) "
65- }
66- return " 0 "
67- } ( ) )
68- . font ( . system( . title, design: . rounded) )
69- . foregroundColor ( . primary)
70- + Text( " steps " )
71- Text ( showSelectionBar ? " \( selectedDate. formatted ( date: . abbreviated, time: . omitted) ) " : " \( earliestDate. formatted ( date: . abbreviated, time: . omitted) ) - \( latestDate. formatted ( date: . abbreviated, time: . omitted) ) " )
72- }
73- . fontWeight ( . semibold)
74- }
7559 var earliestDate : Date {
76- data ( ) . compactMap ( { $0. date } ) . min ( ) ?? Date ( )
60+ weekSteps ( ) . compactMap ( { $0. date } ) . min ( ) ?? Date ( )
7761 }
7862 var latestDate : Date {
79- data ( ) . compactMap ( { $0. date } ) . max ( ) ?? Date ( )
63+ weekSteps ( ) . compactMap ( { $0. date } ) . max ( ) ?? Date ( )
8064 }
8165
66+ let columns = Array ( repeating: GridItem ( . flexible( ) ) , count: 7 )
67+
8268 var body : some View {
8369 Group {
84- // Section {
85- // Picker("Range", selection: $stepChartDataSelection) {
86- // Text("D").tag(0)
87- // Text("W").tag(1)
88- // Text("M").tag(2)
89- // Text("6M").tag(3)
90- // Text("Y").tag(4)
91- // }
92- // .pickerStyle(.segmented)
93- // .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
94- // .listRowBackground(Color.clear)
95- // }
96- Section ( header: header ( ) ) {
70+ Section {
9771 Chart {
9872 RuleMark ( y: . value( " Daily Goal " , deviceManager. settings. stepsGoal) )
9973 . foregroundStyle ( . green)
10074 . lineStyle ( StrokeStyle ( lineWidth: 2 , dash: [ 4 ] ) )
101- ForEach ( data ( ) , id: \. date) {
75+ ForEach ( weekSteps ( ) , id: \. date) {
10276 BarMark (
10377 x: . value( " Date " , $0. date, unit: . weekday) ,
10478 y: . value( " Steps " , $0. steps)
@@ -129,7 +103,7 @@ struct StepChartView: View {
129103
130104 let ( day, _) = proxy. value ( at: location, as: ( Date, Int) . self) ?? ( Date ( ) , 0 )
131105 // We compare the formatted dates because the dates are too specific otherwise
132- let steps = data ( ) . first ( where: { $0. date. formatted ( . dateTime. dayOfYear ( ) ) == day. formatted ( . dateTime. dayOfYear ( ) ) } ) ? . steps ?? 0
106+ let steps = weekSteps ( ) . first ( where: { $0. date. formatted ( . dateTime. dayOfYear ( ) ) == day. formatted ( . dateTime. dayOfYear ( ) ) } ) ? . steps ?? 0
133107
134108 selectedDate = day
135109 selectedSteps = steps
@@ -141,12 +115,51 @@ struct StepChartView: View {
141115 }
142116 }
143117 . chartXAxis {
144- AxisMarks ( values: data ( ) . map ( { $0. date } ) ) {
118+ AxisMarks ( values: weekSteps ( ) . map ( { $0. date } ) ) {
145119 AxisGridLine ( )
146120 AxisValueLabel ( format: . dateTime. weekday ( . abbreviated) )
147121 }
148122 }
149123 . frame ( height: 250 )
124+ } header: {
125+ VStack ( alignment: . leading) {
126+ Text ( weekSteps ( ) . count > 1 ? showSelectionBar ? " Total " : " Average " : " " )
127+ Text ( {
128+ if showSelectionBar {
129+ return " \( selectedSteps) "
130+ } else if !weekSteps( ) . isEmpty {
131+ return " \( weekSteps ( ) . reduce ( 0 ) { $0 + $1. steps } ) "
132+ }
133+ return " 0 "
134+ } ( ) )
135+ . font ( . system( . title, design: . rounded) )
136+ . foregroundColor ( . primary)
137+ + Text( " steps " )
138+ Text ( showSelectionBar ? " \( selectedDate. formatted ( date: . abbreviated, time: . omitted) ) " : " \( earliestDate. formatted ( date: . abbreviated, time: . omitted) ) - \( latestDate. formatted ( date: . abbreviated, time: . omitted) ) " )
139+ }
140+ . fontWeight ( . semibold)
141+ }
142+ . listRowBackground ( Color . clear)
143+ . listRowInsets ( EdgeInsets ( top: 18 , leading: 0 , bottom: 0 , trailing: 0 ) )
144+ Section {
145+ if stepCountManager. hasReachedStepGoal {
146+ Text ( " Today you reached your daily step goal! Keep it up, and let's see how many more days can you reach it... " )
147+ } else {
148+ let encouragementString : String = {
149+ if ( stepCountManager. stepGoal - bleManager. stepCount) <= 1000 {
150+ return " Take a short walk or a start an activity to complete your goal. "
151+ }
152+ return " Set aside some time to complete a few activities to reach your goal. "
153+ } ( )
154+
155+ Text ( " Your daily step goal is \( stepCountManager. stepGoal - bleManager. stepCount) steps away. \( encouragementString) " )
156+ }
157+ }
158+ Section {
159+ // TODO: add a monthly overview chart
160+ } header: {
161+ Text ( " Monthly Overview • \( earliestDate. formatted ( date: . abbreviated, time: . omitted) ) - \( latestDate. formatted ( date: . abbreviated, time: . omitted) ) " )
162+ . fontWeight ( . semibold)
150163 }
151164 . listRowBackground ( Color . clear)
152165 . listRowInsets ( EdgeInsets ( top: 18 , leading: 0 , bottom: 0 , trailing: 0 ) )
0 commit comments