GlucosePercentileDetailView.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import SwiftUI
  2. struct GlucoseDailyPercentileDetailView: View {
  3. let dayData: GlucoseDailyPercentileStats
  4. let units: GlucoseUnits
  5. let dateRangeText: String
  6. // Binding to the parent's selectedPercentile
  7. @Binding var selectedPercentile: GlucosePercentileType?
  8. var body: some View {
  9. VStack(alignment: .center, spacing: 8) {
  10. Text(dateRangeText)
  11. .font(.subheadline.weight(.medium))
  12. .padding(.bottom, 4)
  13. // Only show percentile details if we have valid data
  14. if dayData.median > 0 {
  15. // Improved percentile display
  16. HStack(spacing: 0) {
  17. percentileItem(label: "Min", value: round(dayData.minimum), type: .minimum)
  18. percentileItem(label: "10%", value: round(dayData.percentile10), type: .percentile10)
  19. percentileItem(label: "25%", value: round(dayData.percentile25), type: .percentile25)
  20. percentileItem(label: "Median", value: round(dayData.median), type: .median)
  21. percentileItem(label: "75%", value: round(dayData.percentile75), type: .percentile75)
  22. percentileItem(label: "90%", value: round(dayData.percentile90), type: .percentile90)
  23. percentileItem(label: "Max", value: round(dayData.maximum), type: .maximum)
  24. }
  25. .padding(.vertical, 8)
  26. } else {
  27. Text("No glucose data available for this day")
  28. .foregroundStyle(.secondary)
  29. .padding()
  30. }
  31. }
  32. }
  33. /// Creates a single percentile item for the detail view
  34. private func percentileItem(
  35. label: String,
  36. value: Double,
  37. type: GlucosePercentileType
  38. ) -> some View {
  39. VStack(spacing: 2) {
  40. Text(Decimal(value).formatted(for: units))
  41. .font(.callout.monospacedDigit())
  42. .foregroundStyle(type == selectedPercentile ? Color.purple : .primary)
  43. Text(label)
  44. .font(.caption2)
  45. .foregroundStyle(type == selectedPercentile ? Color.purple : .secondary)
  46. }
  47. .frame(maxWidth: .infinity)
  48. .padding(4)
  49. .background(
  50. RoundedRectangle(cornerRadius: 4)
  51. .fill(type == selectedPercentile ? Color.purple.opacity(0.1) : Color.clear)
  52. .overlay(
  53. RoundedRectangle(cornerRadius: 4)
  54. .strokeBorder(type == selectedPercentile ? Color.purple : Color.clear, lineWidth: 1)
  55. )
  56. )
  57. .contentShape(Rectangle())
  58. .onTapGesture {
  59. withAnimation {
  60. // Toggle selection on tap
  61. selectedPercentile = (selectedPercentile == type) ? nil : type
  62. }
  63. }
  64. }
  65. }