107 lines
4.8 KiB
Swift
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()
|
|
})
|
|
}
|
|
}
|
|
}
|