/ BalanceKit / WorkoutView.swift
WorkoutView.swift
  1  //
  2  //  WorkoutView.swift
  3  //  BalanceKit
  4  //
  5  //  Created by Alexander Kunau on 12.07.25.
  6  //
  7  
  8  import SwiftUI
  9  
 10  struct WorkoutView: View {
 11      @ObservedObject var workoutManager: WorkoutManager
 12      @ObservedObject var userProfile: UserProfile
 13      @EnvironmentObject var dataManager: FoodDataManager // Hinzugefügt für Zugriff auf healthManager
 14      @State private var showingAddWorkout = false
 15      @State private var selectedDate = Date()
 16      @State private var selectedTab = 0
 17      
 18      var body: some View {
 19          VStack(spacing: 0) {
 20              // Tab Selector
 21              Picker("Ansicht", selection: $selectedTab) {
 22                  Text("Übersicht").tag(0)
 23                  Text("Training").tag(1)
 24              }
 25              .pickerStyle(.segmented)
 26              .padding()
 27              
 28              if selectedTab == 0 {
 29                  // Dashboard Ansicht
 30                  WorkoutDashboardView(workoutManager: workoutManager)
 31              } else {
 32                  // Original Training Liste
 33                  trainingListView
 34              }
 35          }
 36          .navigationTitle("Workout Tracker")
 37          .toolbar {
 38              if selectedTab == 1 {
 39                  ToolbarItem(placement: .navigationBarTrailing) {
 40                      Button {
 41                          showingAddWorkout = true
 42                      } label: {
 43                          Label("Hinzufügen", systemImage: "plus")
 44                      }
 45                  }
 46              }
 47          }
 48          .sheet(isPresented: $showingAddWorkout) {
 49              AddWorkoutView(workoutManager: workoutManager, userProfile: userProfile, date: selectedDate)
 50          }
 51      }
 52      
 53      private var trainingListView: some View {
 54          List {
 55              // Empty section for top spacing
 56              Section {
 57                  EmptyView()
 58              }
 59              .frame(height: 0)
 60              .listRowBackground(Color.clear)
 61              
 62              Section(header: Text("Kalender")) {
 63                  DatePicker("Datum", selection: $selectedDate, displayedComponents: .date)
 64                      .datePickerStyle(.compact)
 65                  
 66                  HStack {
 67                      Text("Verbrannte Kalorien heute:")
 68                          .font(.headline)
 69                      Spacer()
 70                      Text("\(workoutManager.totalCaloriesBurnedWithHealthKit(date: selectedDate, healthManager: dataManager.healthManager)) kcal")
 71                          .fontWeight(.bold)
 72                          .foregroundColor(.green)
 73                  }
 74                  
 75                  HStack {
 76                      Text("Verbrannte Kalorien diese Woche:")
 77                          .font(.headline)
 78                      Spacer()
 79                      Text("\(workoutManager.totalCaloriesBurnedForWeek(startingFrom: selectedDate)) kcal")
 80                          .fontWeight(.bold)
 81                          .foregroundColor(.blue)
 82                  }
 83              }
 84              
 85              Section(header: Text("Trainingseinheiten für \(formattedDate)")) {
 86                  let dayWorkouts = workoutManager.workoutsForDay(selectedDate)
 87                  
 88                  if dayWorkouts.isEmpty {
 89                      Text("Keine Trainingseinheiten an diesem Tag")
 90                          .foregroundColor(.secondary)
 91                          .italic()
 92                  } else {
 93                      ForEach(dayWorkouts) { workout in
 94                          VStack(alignment: .leading, spacing: 4) {
 95                              HStack {
 96                                  Image(systemName: workout.type.icon)
 97                                      .foregroundColor(.blue)
 98                                      .frame(width: 24, height: 24)
 99                                  
100                                  VStack(alignment: .leading) {
101                                      Text(workout.type.rawValue)
102                                          .font(.headline)
103                                      
104                                      Text(formattedTime(for: workout.date))
105                                          .font(.caption)
106                                          .foregroundColor(.secondary)
107                                  }
108                                  
109                                  Spacer()
110                                  
111                                  VStack(alignment: .trailing) {
112                                      Text("\(workout.caloriesBurned) kcal")
113                                          .fontWeight(.bold)
114                                          .foregroundColor(.green)
115                                      
116                                      Text("\(Int(workout.duration / 60)) Min.")
117                                          .font(.caption)
118                                          .foregroundColor(.secondary)
119                                  }
120                              }
121                              
122                              if !workout.notes.isEmpty {
123                                  Text(workout.notes)
124                                      .font(.caption)
125                                      .foregroundColor(.secondary)
126                                      .padding(.leading, 28)
127                              }
128                          }
129                          .padding(.vertical, 4)
130                      }
131                      .onDelete { indexSet in
132                          // Konvertiere Indizes aus der gefilterten Liste in Indizes der Hauptliste
133                          let workoutsToDelete = indexSet.map { dayWorkouts[$0] }
134                          for workout in workoutsToDelete {
135                              if let index = workoutManager.workouts.firstIndex(where: { $0.id == workout.id }) {
136                                  workoutManager.workouts.remove(at: index)
137                              }
138                          }
139                      }
140                  }
141              }
142              
143              // Zusätzliche Informationen für den Benutzer
144              VStack(alignment: .leading, spacing: 4) {
145                  Text("Hinweis:")
146                      .font(.caption)
147                      .fontWeight(.bold)
148                  Text("Verbrannte Kalorien werden in der Tagesübersicht automatisch von deiner Kalorienbilanz abgezogen.")
149                      .font(.caption)
150                      .foregroundColor(.secondary)
151              }
152              .padding(.vertical, 6)
153          }
154      }
155      
156      private var formattedDate: String {
157          let formatter = DateFormatter()
158          formatter.dateStyle = .medium
159          return formatter.string(from: selectedDate)
160      }
161      
162      private func formattedTime(for date: Date) -> String {
163          let formatter = DateFormatter()
164          formatter.timeStyle = .short
165          return formatter.string(from: date)
166      }
167  }
168  
169  struct AddWorkoutView: View {
170      @Environment(\.dismiss) private var dismiss
171      @ObservedObject var workoutManager: WorkoutManager
172      @ObservedObject var userProfile: UserProfile
173      
174      var date: Date
175      
176      @State private var selectedWorkoutType: WorkoutType = .running
177      @State private var duration = 30.0 // in Minuten
178      @State private var notes = ""
179      
180      var body: some View {
181          NavigationStack {
182              Form {
183                  Section(header: Text("Trainingsdetails")) {
184                      Picker("Trainingsart", selection: $selectedWorkoutType) {
185                          ForEach(WorkoutType.allCases) { type in
186                              Label {
187                                  Text(type.rawValue)
188                              } icon: {
189                                  Image(systemName: type.icon)
190                              }
191                              .tag(type)
192                          }
193                      }
194                      
195                      VStack(alignment: .leading) {
196                          Text("Dauer: \(Int(duration)) Minuten")
197                          Slider(value: $duration, in: 5...180, step: 5)
198                      }
199                      
200                      // Kalorienvorschau
201                      HStack {
202                          Text("Geschätzte Kalorien:")
203                          Spacer()
204                          Text("\(estimatedCalories) kcal")
205                              .fontWeight(.bold)
206                              .foregroundColor(.green)
207                      }
208                      
209                      TextField("Notizen (optional)", text: $notes)
210                  }
211                  
212                  Section {
213                      Button("Speichern") {
214                          workoutManager.addWorkout(
215                              type: selectedWorkoutType,
216                              durationInMinutes: duration,
217                              date: date,
218                              userWeight: userProfile.weight,
219                              notes: notes
220                          )
221                          dismiss()
222                      }
223                  }
224              }
225              .navigationTitle("Training hinzufügen")
226              .navigationBarTitleDisplayMode(.inline)
227              .toolbar {
228                  ToolbarItem(placement: .cancellationAction) {
229                      Button("Abbrechen") {
230                          dismiss()
231                      }
232                  }
233              }
234          }
235      }
236      
237      // Berechnung der geschätzten Kalorien basierend auf den aktuellen Eingaben
238      private var estimatedCalories: Int {
239          Workout.calculateCalories(
240              type: selectedWorkoutType,
241              durationInMinutes: duration,
242              weightInKg: userProfile.weight
243          )
244      }
245  }
246  
247  #Preview {
248      NavigationStack {
249          WorkoutView(workoutManager: WorkoutManager(), userProfile: UserProfile())
250      }
251  }