MealStatsView.swift 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import Charts
  2. import SwiftUI
  3. struct MealStatsView: View {
  4. let mealStats: [MealStats]
  5. let selectedDuration: Stat.StateModel.Duration
  6. var body: some View {
  7. VStack(alignment: .leading, spacing: 8) {
  8. Text("Macronutrients")
  9. .font(.headline)
  10. Chart(mealStats) { stat in
  11. // Carbs Bar
  12. BarMark(
  13. x: .value("Date", stat.date, unit: .day),
  14. y: .value("Amount", stat.carbs),
  15. width: .ratio(0.6)
  16. )
  17. .foregroundStyle(Color.orange)
  18. .position(by: .value("Nutrient", "Carbs"))
  19. // Fat Bar
  20. BarMark(
  21. x: .value("Date", stat.date, unit: .day),
  22. y: .value("Amount", stat.fat),
  23. width: .ratio(0.6)
  24. )
  25. .foregroundStyle(Color.yellow)
  26. .position(by: .value("Nutrient", "Fat"))
  27. // Protein Bar
  28. BarMark(
  29. x: .value("Date", stat.date, unit: .day),
  30. y: .value("Amount", stat.protein),
  31. width: .ratio(0.6)
  32. )
  33. .foregroundStyle(Color.green)
  34. .position(by: .value("Nutrient", "Protein"))
  35. }
  36. .chartForegroundStyleScale([
  37. "Carbs": Color.orange,
  38. "Fat": Color.yellow,
  39. "Protein": Color.green
  40. ])
  41. .chartLegend(position: .bottom, alignment: .leading, spacing: 12)
  42. .frame(height: 200)
  43. .chartXAxis {
  44. mealChartXAxisMarks
  45. }
  46. .chartYAxis {
  47. mealChartYAxisMarks
  48. }
  49. }
  50. }
  51. private var mealChartXAxisMarks: some AxisContent {
  52. AxisMarks { value in
  53. if let date = value.as(Date.self) {
  54. AxisValueLabel {
  55. switch selectedDuration {
  56. case .Day,
  57. .Today,
  58. .Week:
  59. Text(date, format: .dateTime.weekday(.abbreviated))
  60. case .Month,
  61. .Total:
  62. Text(date, format: .dateTime.day().month(.defaultDigits))
  63. }
  64. }
  65. AxisGridLine()
  66. }
  67. }
  68. }
  69. private var mealChartYAxisMarks: some AxisContent {
  70. AxisMarks(position: .leading) { value in
  71. if let amount = value.as(Double.self) {
  72. AxisValueLabel {
  73. Text("\(Int(amount))g")
  74. }
  75. AxisGridLine()
  76. }
  77. }
  78. }
  79. }