DataTableRootView.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import SwiftUI
  2. import Swinject
  3. extension DataTable {
  4. struct RootView: BaseView {
  5. let resolver: Resolver
  6. @StateObject var state = StateModel()
  7. @State private var isRemoveCarbsAlertPresented = false
  8. @State private var removeCarbsAlert: Alert?
  9. private var glucoseFormatter: NumberFormatter {
  10. let formatter = NumberFormatter()
  11. formatter.numberStyle = .decimal
  12. formatter.maximumFractionDigits = 0
  13. if state.units == .mmolL {
  14. formatter.minimumFractionDigits = 1
  15. formatter.maximumFractionDigits = 1
  16. }
  17. formatter.roundingMode = .halfUp
  18. return formatter
  19. }
  20. private var dateFormatter: DateFormatter {
  21. let formatter = DateFormatter()
  22. formatter.timeStyle = .short
  23. return formatter
  24. }
  25. var body: some View {
  26. VStack {
  27. Picker("Mode", selection: $state.mode) {
  28. ForEach(Mode.allCases.indexed(), id: \.1) { index, item in
  29. Text(item.name).tag(index)
  30. }
  31. }
  32. .pickerStyle(SegmentedPickerStyle())
  33. .padding(.horizontal)
  34. Form {
  35. switch state.mode {
  36. case .treatments: treatmentsList
  37. case .glucose: glucoseList
  38. }
  39. }
  40. }
  41. .onAppear(perform: configureView)
  42. .navigationTitle("History")
  43. .navigationBarTitleDisplayMode(.automatic)
  44. .navigationBarItems(
  45. leading: Button("Close", action: state.hideModal),
  46. trailing: state.mode == .glucose ? EditButton().asAny() : EmptyView().asAny()
  47. )
  48. }
  49. private var treatmentsList: some View {
  50. List {
  51. ForEach(state.treatments) { item in
  52. treatmentView(item)
  53. }
  54. }
  55. }
  56. private var glucoseList: some View {
  57. List {
  58. ForEach(state.glucose) { item in
  59. gluciseView(item)
  60. }.onDelete(perform: deleteGlucose)
  61. }
  62. }
  63. @ViewBuilder private func treatmentView(_ item: Treatment) -> some View {
  64. HStack {
  65. Image(systemName: "circle.fill").foregroundColor(item.color)
  66. Text(dateFormatter.string(from: item.date))
  67. .moveDisabled(true)
  68. Text(item.type.name)
  69. Text(item.amountText).foregroundColor(.secondary)
  70. if let duration = item.durationText {
  71. Text(duration).foregroundColor(.secondary)
  72. }
  73. if item.type == .carbs {
  74. Spacer()
  75. Image(systemName: "xmark.circle").foregroundColor(.secondary)
  76. .contentShape(Rectangle())
  77. .padding(.vertical)
  78. .onTapGesture {
  79. removeCarbsAlert = Alert(
  80. title: Text("Delete carbs?"),
  81. message: Text(item.amountText),
  82. primaryButton: .destructive(
  83. Text("Delete"),
  84. action: { state.deleteCarbs(at: item.date) }
  85. ),
  86. secondaryButton: .cancel()
  87. )
  88. isRemoveCarbsAlertPresented = true
  89. }
  90. .alert(isPresented: $isRemoveCarbsAlertPresented) {
  91. removeCarbsAlert!
  92. }
  93. }
  94. }
  95. }
  96. @ViewBuilder private func gluciseView(_ item: Glucose) -> some View {
  97. VStack(alignment: .leading, spacing: 4) {
  98. HStack {
  99. Text(dateFormatter.string(from: item.glucose.dateString))
  100. Spacer()
  101. Text(item.glucose.glucose.map {
  102. glucoseFormatter.string(from: Double(
  103. state.units == .mmolL ? $0.asMmolL : Decimal($0)
  104. ) as NSNumber)!
  105. } ?? "--")
  106. Text(state.units.rawValue)
  107. Text(item.glucose.direction?.symbol ?? "--")
  108. }
  109. Text("ID: " + item.glucose.id).font(.caption2).foregroundColor(.secondary)
  110. }
  111. }
  112. private func deleteGlucose(at offsets: IndexSet) {
  113. state.deleteGlucose(at: offsets[offsets.startIndex])
  114. }
  115. }
  116. }