| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- import SwiftUI
- struct PopupView: View {
- @StateObject var state: Bolus.StateModel
- @Environment(\.colorScheme) var colorScheme
- private var fractionDigits: Int {
- if state.units == .mmolL {
- return 1
- } else { return 0 }
- }
- var body: some View {
- NavigationStack {
- ScrollView {
- Grid(alignment: .topLeading, horizontalSpacing: 3, verticalSpacing: 0) {
- GridRow {
- Text("Calculations").fontWeight(.bold).gridCellColumns(3).gridCellAnchor(.center).padding(.vertical)
- }
- calcSettingsFirstRow
- calcSettingsSecondRow
- DividerCustom()
- // meal entries as grid rows
- if state.carbs > 0 {
- GridRow {
- Text("Carbs").foregroundColor(.secondary)
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- HStack {
- Text(state.carbs.formatted())
- Text("g").foregroundColor(.secondary)
- }.gridCellAnchor(.trailing)
- }
- }
- if state.fat > 0 {
- GridRow {
- Text("Fat").foregroundColor(.secondary)
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- HStack {
- Text(state.fat.formatted())
- Text("g").foregroundColor(.secondary)
- }.gridCellAnchor(.trailing)
- }
- }
- if state.protein > 0 {
- GridRow {
- Text("Protein").foregroundColor(.secondary)
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- HStack {
- Text(state.protein.formatted())
- Text("g").foregroundColor(.secondary)
- }.gridCellAnchor(.trailing)
- }
- }
- if state.carbs > 0 || state.protein > 0 || state.fat > 0 {
- DividerCustom()
- }
- GridRow {
- Text("Detailed Calculation Steps").gridCellColumns(3).gridCellAnchor(.center)
- .padding(.bottom, 10)
- }
- calcGlucoseFirstRow
- calcGlucoseSecondRow.padding(.bottom, 5)
- calcGlucoseFormulaRow
- DividerCustom()
- calcIOBRow
- DividerCustom()
- calcCOBRow.padding(.bottom, 5)
- calcCOBFormulaRow
- DividerCustom()
- calcDeltaRow
- calcDeltaFormulaRow
- DividerCustom()
- calcFullBolusRow
- if state.useSuperBolus {
- DividerCustom()
- calcSuperBolusRow
- }
- DividerDouble()
- calcResultRow
- calcResultFormulaRow
- }
- Spacer()
- Button { state.showInfo = false }
- label: { Text("Got it!").frame(maxWidth: .infinity, alignment: .center) }
- .buttonStyle(.bordered)
- .padding(.top)
- }
- .padding([.horizontal, .bottom])
- .font(.subheadline)
- }
- }
- var calcSettingsFirstRow: some View {
- GridRow {
- Group {
- Text("Carb Ratio:")
- .foregroundColor(.secondary)
- }.gridCellAnchor(.leading)
- Group {
- Text("ISF:")
- .foregroundColor(.secondary)
- }.gridCellAnchor(.leading)
- VStack {
- Text("Target:")
- .foregroundColor(.secondary)
- }.gridCellAnchor(.leading)
- }
- }
- var calcSettingsSecondRow: some View {
- GridRow {
- Text(state.carbRatio.formatted() + " " + NSLocalizedString("g/U", comment: " grams per Unit"))
- .gridCellAnchor(.leading)
- Text(
- state.isf.formatted() + " " + state.units
- .rawValue + NSLocalizedString("/U", comment: "/Insulin unit")
- ).gridCellAnchor(.leading)
- let target = state.units == .mmolL ? state.target.asMmolL : state.target
- Text(
- target
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) +
- " " + state.units.rawValue
- ).gridCellAnchor(.leading)
- }
- }
- var calcGlucoseFirstRow: some View {
- GridRow(alignment: .center) {
- let currentBG = state.units == .mmolL ? state.currentBG.asMmolL : state.currentBG
- let target = state.units == .mmolL ? state.target.asMmolL : state.target
- Text("Glucose:").foregroundColor(.secondary)
- let targetDifference = state.units == .mmolL ? state.targetDifference.asMmolL : state.targetDifference
- let firstRow = currentBG
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits)))
- + " - " +
- target
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits)))
- + " = " +
- targetDifference
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits)))
- Text(firstRow).frame(minWidth: 0, alignment: .leading).foregroundColor(.secondary)
- .gridColumnAlignment(.leading)
- HStack {
- Text(
- self.insulinRounder(state.targetDifferenceInsulin).formatted()
- )
- Text("U").foregroundColor(.secondary)
- }.fontWeight(.bold)
- .gridColumnAlignment(.trailing)
- }
- }
- var calcGlucoseSecondRow: some View {
- GridRow(alignment: .center) {
- let currentBG = state.units == .mmolL ? state.currentBG.asMmolL : state.currentBG
- Text(
- currentBG
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) +
- " " +
- state.units.rawValue
- )
- let targetDifference = state.units == .mmolL ? state.targetDifference.asMmolL : state.targetDifference
- let secondRow = targetDifference
- .formatted(
- .number.grouping(.never).rounded()
- .precision(.fractionLength(fractionDigits))
- )
- + " / " +
- state.isf.formatted()
- + " ≈ " +
- self.insulinRounder(state.targetDifferenceInsulin).formatted()
- Text(secondRow).foregroundColor(.secondary).gridColumnAlignment(.leading)
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- }
- }
- var calcGlucoseFormulaRow: some View {
- GridRow(alignment: .top) {
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- Text("(Current - Target) / ISF").foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8))
- .gridColumnAlignment(.leading)
- .gridCellColumns(2)
- }
- .font(.caption)
- }
- var calcIOBRow: some View {
- GridRow(alignment: .center) {
- HStack {
- Text("IOB:").foregroundColor(.secondary)
- Text(
- self.insulinRounder(state.iob).formatted()
- )
- }
- Text("Subtract IOB").foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8)).font(.footnote)
- let iobFormatted = self.insulinRounder(state.iob).formatted()
- HStack {
- Text((state.iob >= 0 ? "-" : "") + (state.iob >= 0 ? iobFormatted : "(" + iobFormatted + ")"))
- Text("U").foregroundColor(.secondary)
- }.fontWeight(.bold)
- .gridColumnAlignment(.trailing)
- }
- }
- var calcCOBRow: some View {
- GridRow(alignment: .center) {
- HStack {
- Text("COB:").foregroundColor(.secondary)
- Text(
- state.wholeCob
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) +
- NSLocalizedString(" g", comment: "grams")
- )
- }
- Text(
- state.wholeCob
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits)))
- + " / " +
- state.carbRatio.formatted()
- + " ≈ " +
- self.insulinRounder(state.wholeCobInsulin).formatted()
- )
- .foregroundColor(.secondary)
- .gridColumnAlignment(.leading)
- HStack {
- Text(
- self.insulinRounder(state.wholeCobInsulin).formatted()
- )
- Text("U").foregroundColor(.secondary)
- }.fontWeight(.bold)
- .gridColumnAlignment(.trailing)
- }
- }
- var calcCOBFormulaRow: some View {
- GridRow(alignment: .center) {
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- Text("COB / Carb Ratio").foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8))
- .gridColumnAlignment(.leading)
- .gridCellColumns(2)
- }
- .font(.caption)
- }
- var calcDeltaRow: some View {
- GridRow(alignment: .center) {
- Text("Delta:").foregroundColor(.secondary)
- let deltaBG = state.units == .mmolL ? state.deltaBG.asMmolL : state.deltaBG
- Text(
- deltaBG
- .formatted(
- .number.grouping(.never).rounded()
- .precision(.fractionLength(fractionDigits))
- )
- + " / " +
- state.isf.formatted()
- + " ≈ " +
- self.insulinRounder(state.fifteenMinInsulin).formatted()
- )
- .foregroundColor(.secondary)
- .gridColumnAlignment(.leading)
- HStack {
- Text(
- self.insulinRounder(state.fifteenMinInsulin).formatted()
- )
- Text("U").foregroundColor(.secondary)
- }.fontWeight(.bold)
- .gridColumnAlignment(.trailing)
- }
- }
- var calcDeltaFormulaRow: some View {
- GridRow(alignment: .center) {
- let deltaBG = state.units == .mmolL ? state.deltaBG.asMmolL : state.deltaBG
- Text(
- deltaBG
- .formatted(
- .number.grouping(.never).rounded()
- .precision(.fractionLength(fractionDigits))
- ) + " " +
- state.units.rawValue
- )
- Text("15min Delta / ISF").font(.caption).foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8))
- .gridColumnAlignment(.leading)
- .gridCellColumns(2).padding(.top, 5)
- }
- }
- var calcFullBolusRow: some View {
- GridRow(alignment: .center) {
- Text("Full Bolus")
- .foregroundColor(.secondary)
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- HStack {
- Text(self.insulinRounder(state.wholeCalc).formatted())
- .foregroundStyle(state.wholeCalc < 0 ? Color.loopRed : Color.primary)
- Text("U").foregroundColor(.secondary)
- }.gridColumnAlignment(.trailing)
- .fontWeight(.bold)
- }
- }
- var calcSuperBolusRow: some View {
- GridRow(alignment: .center) {
- Text("Super Bolus")
- .foregroundColor(.secondary)
- Text("Added to Result").foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8)).font(.footnote)
- HStack {
- Text("+" + self.insulinRounder(state.superBolusInsulin).formatted())
- .foregroundStyle(Color.loopRed)
- Text("U").foregroundColor(.secondary)
- }.gridColumnAlignment(.trailing)
- .fontWeight(.bold)
- }
- }
- var calcResultRow: some View {
- GridRow(alignment: .center) {
- Text("Result").fontWeight(.bold)
- HStack {
- Text(state.useSuperBolus ? "(" : "")
- .foregroundColor(.loopRed)
- + Text(state.fraction.formatted())
- + Text(" x ")
- .foregroundColor(.secondary)
- // if fatty meal is chosen
- + Text(state.useFattyMealCorrectionFactor ? state.fattyMealFactor.formatted() : "")
- .foregroundColor(.orange)
- + Text(state.useFattyMealCorrectionFactor ? " x " : "")
- .foregroundColor(.secondary)
- // endif fatty meal is chosen
- + Text(self.insulinRounder(state.wholeCalc).formatted())
- .foregroundColor(state.wholeCalc < 0 ? Color.loopRed : Color.primary)
- // if superbolus is chosen
- + Text(state.useSuperBolus ? ")" : "")
- .foregroundColor(.loopRed)
- + Text(state.useSuperBolus ? " + " : "")
- .foregroundColor(.secondary)
- + Text(state.useSuperBolus ? state.superBolusInsulin.formatted() : "")
- .foregroundColor(.loopRed)
- // endif superbolus is chosen
- + Text(" ≈ ")
- .foregroundColor(.secondary)
- }
- .gridColumnAlignment(.leading)
- HStack {
- Text(self.insulinRounder(state.insulinCalculated).formatted())
- .fontWeight(.bold)
- .foregroundColor(state.wholeCalc >= state.maxBolus ? Color.loopRed : Color.blue)
- Text("U").foregroundColor(.secondary)
- }
- .gridColumnAlignment(.trailing)
- .fontWeight(.bold)
- }
- }
- var calcResultFormulaRow: some View {
- GridRow(alignment: .bottom) {
- if state.useFattyMealCorrectionFactor {
- Group {
- Text("Factor x Fatty Meal Factor x Full Bolus")
- .foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8))
- +
- Text(state.wholeCalc > state.maxBolus ? " ≈ Max Bolus" : "").foregroundColor(Color.loopRed)
- }
- .font(.caption)
- .gridCellAnchor(.center)
- .gridCellColumns(3)
- } else if state.useSuperBolus {
- Group {
- Text("(Factor x Full Bolus) + Super Bolus")
- .foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8))
- +
- Text(state.wholeCalc > state.maxBolus ? " ≈ Max Bolus" : "").foregroundColor(Color.loopRed)
- }
- .font(.caption)
- .gridCellAnchor(.center)
- .gridCellColumns(3)
- } else {
- Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])
- Group {
- Text("Factor x Full Bolus")
- .foregroundColor(.secondary.opacity(colorScheme == .dark ? 0.65 : 0.8))
- +
- Text(state.wholeCalc > state.maxBolus ? " ≈ Max Bolus" : "").foregroundColor(Color.loopRed)
- }
- .font(.caption)
- .padding(.top, 5)
- .gridCellAnchor(.leading)
- .gridCellColumns(2)
- }
- }
- }
- private func insulinRounder(_ value: Decimal) -> Decimal {
- let toRound = NSDecimalNumber(decimal: value).doubleValue
- return Decimal(floor(100 * toRound) / 100)
- }
- struct DividerDouble: View {
- var body: some View {
- VStack(spacing: 2) {
- Rectangle()
- .frame(height: 1)
- .foregroundColor(.gray.opacity(0.65))
- Rectangle()
- .frame(height: 1)
- .foregroundColor(.gray.opacity(0.65))
- }
- .frame(height: 4)
- .padding(.vertical)
- }
- }
- struct DividerCustom: View {
- var body: some View {
- Rectangle()
- .frame(height: 1)
- .foregroundColor(.gray.opacity(0.65))
- .padding(.vertical)
- }
- }
- }
- // #Preview {
- // PopupView()
- // }
|