init
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import SwiftUI
|
||||
|
||||
struct DashboardView: View {
|
||||
@Environment(DeviceStore.self) private var store
|
||||
@Environment(BluetoothManager.self) private var bluetooth
|
||||
|
||||
@State private var isAddingDevice = false
|
||||
@State private var isManagingProfiles = false
|
||||
|
||||
private let columns = [GridItem(.adaptive(minimum: 300), spacing: 16)]
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollView {
|
||||
if !bluetooth.isBluetoothReady {
|
||||
statusBanner
|
||||
}
|
||||
|
||||
if store.activeDevices.isEmpty {
|
||||
emptyState
|
||||
} else {
|
||||
LazyVGrid(columns: columns, spacing: 16) {
|
||||
ForEach(store.activeDevices) { device in
|
||||
NavigationLink {
|
||||
DeviceDetailView(device: device)
|
||||
} label: {
|
||||
DeviceCard(
|
||||
device: device,
|
||||
snapshot: bluetooth.snapshots[device.id],
|
||||
linkState: bluetooth.linkStates[device.id] ?? .searching
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
}
|
||||
.background(Color(.systemGroupedBackground))
|
||||
.navigationTitle(store.activeProfile?.name ?? "Camper")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
profileMenu
|
||||
}
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button("Gerät hinzufügen", systemImage: "plus") {
|
||||
isAddingDevice = true
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isAddingDevice) {
|
||||
AddDeviceView()
|
||||
}
|
||||
.sheet(isPresented: $isManagingProfiles) {
|
||||
ProfilesView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Umschalter zwischen den Fahrzeugen.
|
||||
private var profileMenu: some View {
|
||||
Menu {
|
||||
Picker("Fahrzeug", selection: Binding(
|
||||
get: { store.activeProfileID },
|
||||
set: { id in
|
||||
guard let profile = store.profiles.first(where: { $0.id == id }) else { return }
|
||||
store.selectProfile(profile)
|
||||
bluetooth.refreshConfiguration()
|
||||
}
|
||||
)) {
|
||||
ForEach(store.profiles) { profile in
|
||||
Label(profile.name, systemImage: profile.symbol).tag(profile.id)
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
Button("Fahrzeuge verwalten…", systemImage: "gearshape") {
|
||||
isManagingProfiles = true
|
||||
}
|
||||
} label: {
|
||||
Label(store.activeProfile?.name ?? "Fahrzeug",
|
||||
systemImage: store.activeProfile?.symbol ?? "box.truck")
|
||||
.labelStyle(.iconOnly)
|
||||
}
|
||||
}
|
||||
|
||||
private var statusBanner: some View {
|
||||
Label(bluetooth.bluetoothStatusText, systemImage: "exclamationmark.triangle.fill")
|
||||
.font(.callout)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding()
|
||||
.background(.orange.opacity(0.15), in: .rect(cornerRadius: 12))
|
||||
.padding(.horizontal)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
|
||||
private var emptyState: some View {
|
||||
ContentUnavailableView {
|
||||
Label("Noch keine Geräte", systemImage: "antenna.radiowaves.left.and.right")
|
||||
} description: {
|
||||
Text("Füge \(store.activeProfile.map { "„\($0.name)“" } ?? "diesem Fahrzeug") "
|
||||
+ "den Ladebooster, den Solarladeregler und das BMS hinzu.")
|
||||
} actions: {
|
||||
Button("Gerät suchen") { isAddingDevice = true }
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.padding(.top, 60)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user