Okay, well, you went ahead anyway. Here's my update:
// ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var tipa: [Double] = []
@State private var costa: [Double] = []
@State private var cost = ""
@State private var costt: Double? = 0.0
@State private var paidt: Double? = 0.0
@State private var paid = ""
@State private var tipp = ""
@State private var tipc = ""
@State private var tipaa = ""
@State private var totalCost = ""
@State private var totalTips = ""
@State private var totalCash = ""
@State private var tipcc = ""
@State private var numbc = ""
@State private var deletep = 0
@State private var number = 0
@State private var errorMsg = ""
var body: some View {
GeometryReader { g in
NavigationStack {
VStack {
HStack {
// No need to manually pad the date out with spaces, which will never be correct.
// Just use an HStack and put a Spacer() in, so it goes: |<.....Spacer().....>Date|
Spacer()
Text(Date().formatted(date: .numeric, time: .omitted))
.foregroundStyle(Color.black)
.fontWeight(.bold)
.padding(.trailing, 10)
}
Text("Driver's Food Delivery")
.font(.largeTitle)
.fontWeight(.bold)
Image("Screenshot 2024")
VStack {
Spacer()
Text(errorMsg)
.foregroundStyle(Color.red)
// Here, put the text in one Text element, and tell SwiftUI to put it on two lines.
// No need for msg/msg2 variables.
Text("Enter cost and how much was paid. Enter numbers and one decimal point only, then press Enter.")
.foregroundStyle(Color.blue)
.lineLimit(2, reservesSpace: true)
Spacer()
}
// Use a Grid to lay out your data; much cleaner, and SwiftUI will keep it in columns for you
Grid(alignment: .center, horizontalSpacing: 6, verticalSpacing: 6) {
GridRow {
Text("Cost")
.gridColumnAlignment(.leading)
Text("Paid")
.gridColumnAlignment(.leading)
Text("Tip")
.gridColumnAlignment(.trailing)
Text("Tip %")
.gridColumnAlignment(.trailing)
}
.font(.headline)
GridRow {
TextField("Cost", text: $cost)
.padding(10)
.background(Color.brown)
.cornerRadius(12)
.frame(width: g.size.width * 0.2)
.gridColumnAlignment(.leading)
TextField("Paid", text: $paid)
.padding(10)
.background(Color.brown)
.cornerRadius(12)
.frame(width: g.size.width * 0.2)
.gridColumnAlignment(.leading)
Text(tipp)
.frame(width: g.size.width * 0.2)
.gridColumnAlignment(.trailing)
Text(tipc)
.frame(width: g.size.width * 0.2)
.gridColumnAlignment(.trailing)
}
}
.padding(.vertical, 20)
HStack {
Button {
enterPayment()
} label: {
Text("Enter")
.font(.title2)
.padding(10)
.background(Color.green)
.foregroundStyle(Color.white)
.cornerRadius(12)
}
.padding(.leading, 10) // Keeps it off the edge of the screen
NavigationLink(destination: ViewDetail()) {
Text("Detail")
.font(.title2)
.padding(10)
.background(Color.blue)
.foregroundStyle(Color.white)
.cornerRadius(12)
}
Spacer() // Leaves a gap between the Enter & Detail buttons, and the destructive Delete button
Button {
delete(costa: &costa, tipa: &tipa, number: &number)
} label: {
Text("Delete")
.font(.title2)
.padding(10)
.background(Color.red)
.foregroundStyle(Color.white)
.cornerRadius(12)
}
.padding(.trailing, 10) // Keeps it off the edge of the screen
}
Divider() // Nice little divider
.padding(.vertical, 20)
}
VStack {
Grid(alignment: .center, horizontalSpacing: 6, verticalSpacing: 6) {
GridRow {
Text("Avg. Tip")
.padding(.horizontal, 20)
Text("Tip %")
.padding(.horizontal, 20)
Text("#")
.padding(.horizontal, 20)
}
.gridColumnAlignment(.center)
.font(.title3)
GridRow {
Text(tipaa)
.padding(.horizontal, 20)
Text(tipcc)
.padding(.horizontal, 20)
Text(numbc)
.padding(.horizontal, 20)
}
.gridColumnAlignment(.center)
.font(.system(size: 22, weight: .bold))
.foregroundStyle(Color.blue)
}
Spacer()
}
VStack {
Grid(alignment: .center, horizontalSpacing: 6, verticalSpacing: 6) {
GridRow {
Text("Total Cost")
.padding(.horizontal, 10)
Text("Total Tips")
.padding(.horizontal, 10)
Text("Total Cash")
.padding(.horizontal, 10)
}
.gridColumnAlignment(.center)
.font(.title3)
GridRow {
Text(totalCost)
.padding(.horizontal, 10)
Text(totalTips)
.padding(.horizontal, 10)
Text(totalCash)
.padding(.horizontal, 10)
}
.gridColumnAlignment(.center)
.font(.system(size: 22, weight: .bold))
.foregroundStyle(Color.blue)
}
Spacer()
}
}
}
}
func enterPayment() {
var ttips = 0.0
var tcost = 0.0
var tipo = 0.00
costt = Double(cost)
paidt = Double(paid)
errorMsg = ""
if(costt != nil && paidt != nil) {
tipo = Double(paid)! - Double(cost)!
tipa.append(tipo)
costa.append(Double(cost)!)
number += 1
numbc = String(number)
ttips = (tipa.reduce(0, +))
tcost = (costa.reduce(0, +))
tipaa = (ttips / Double(number)).formatted(.currency(code: "USD"))
totalTips = ttips.formatted(.currency(code: "USD"))
totalCost = tcost.formatted(.currency(code: "USD"))
tipp = tipo.formatted(.currency(code: "USD"))
tipc = String(tipo / Double(cost)! * 100)
tipc = String(format: "%3.0f%%", Double(tipc)!)
tipcc = String(ttips / tcost * 100)
tipcc = String(format: "%3.0f%%", Double(tipcc)!)
totalCash = (tcost + ttips).formatted(.currency(code: "USD"))
} else {
errorMsg = "Enter numbers and 1 decimal point only."
}
}
}
struct ViewDetail: View {
@State var text1: String = ""
@State var tip1: String = ""
@State var text23: String = ""
@State var tip23: String = ""
var body: some View {
Text(text1)
Text(tip1)
Text(text23)
Text(tip23)
}
func detailLine(costa: inout [Double], tipa: inout [Double]) {
print(costa, tipa)
text1 = "125"
print("detail")
}
}
func delete(costa: inout [Double], tipa: inout [Double], number: inout Int) {
print(costa, tipa)
tipa.removeLast()
costa.removeLast()
number -= 1
print(costa,tipa)
}
#Preview {
ContentView()
}