Files
meterios/meterios/views/MainView.swift
T
2025-04-02 14:39:51 +02:00

107 lines
4.8 KiB
Swift

//
// MainView.swift
// meterios
//
// (c) 2025 Martin "maride" Dessauer
//
import SwiftUI
import OSLog
struct MainView: View {
@AppStorage("meteHostAddr") private var meteHostAddr = ""
@AppStorage("meteUserID") private var meteUserID = -1
@State private var availableDrinks: Array<Drink> = []
@State private var outOfOrderDrinks: Array<Drink> = []
@State private var user: User = User.init(meteID: 0, displayName: "", displayImageURL: "", balance: 0.00)
@Environment(\.dismiss) var dismiss
// Update pulls drinks off the backend and updates the user info (balance, name, profile pic)
func update() {
Task {
do {
user = try await BackendConnector().GetUser(baseAddr: meteHostAddr, userID: meteUserID)
let drinks = try await BackendConnector().GetDrinks(baseAddr: meteHostAddr)
availableDrinks = drinks.filter({ $0.active })
outOfOrderDrinks = drinks.filter({ !$0.active })
} catch {
let _ = Logger().error("Failed to update from \(meteHostAddr): \(error)")
}
}
}
var body: some View {
ScrollViewReader { scrollViewReader in
NavigationView {
VStack(alignment: .leading) {
List () {
// Account
Section(header: Text("Account").id("topAnchor")) {
NavigationLink(destination: UserDetailView(user: user)) {
Button(action: {
dismiss()
}) {
HStack {
// Profile Image
AsyncImage(
url: URL(string: user.displayImageURL),
content: { image in image.resizable().aspectRatio(contentMode: .fill).frame(width: 64, height: 64).clipShape(Circle()) },
placeholder: {
ZStack {
Circle().fill(.gray).frame(width: 64, height: 64)
ProgressView()
}
}
).fixedSize()
Spacer(minLength: 16.0)
// Account, Address & Balance
VStack(alignment: .leading) {
HStack {
Text(user.displayName).fontWeight(.bold)
Divider()
Text(String(format: "%.2f€", user.balance)).foregroundStyle(user.balance > 0 ? .green : .red)
}.fixedSize()
Text("\(meteHostAddr)").fontWeight(.thin)
}.fixedSize()
}.fixedSize()
}
}
}
// Drinks list
if !availableDrinks.isEmpty {
Section(header: Text("Available")) {
ForEach(availableDrinks) { drink in
NavigationLink(drink.name) {
DrinkDetail(drink: drink).onDisappear(perform: {
update()
scrollViewReader.scrollTo("topAnchor", anchor: .top)
})
}
}
}
}
if !outOfOrderDrinks.isEmpty {
Section(header: Text("Out of stock")) {
ForEach(outOfOrderDrinks) { drink in
NavigationLink(drink.name) {
DrinkDetail(drink: drink)
}
}
}
}
}.navigationTitle("Meterios").refreshable(action: {
update()
})
}
}.onAppear(perform: {
update()
})
}
}
}