USB-Meter / USB Meter / Views / ChargedDevices / SidebarChargedDevicesSectionView.swift
1 contributor
109 lines | 4.052kb
//
//  SidebarChargedDevicesSectionView.swift
//  USB Meter
//
//  Created by Codex on 10/04/2026.
//

import SwiftUI

struct SidebarChargedDevicesSectionView: View {
    let title: String
    let chargedDevices: [ChargedDeviceSummary]
    let emptyStateText: String
    let tint: Color
    let onAdd: () -> Void

    var body: some View {
        Section(header: headerView) {
            if chargedDevices.isEmpty {
                Text(emptyStateText)
                    .font(.footnote)
                    .foregroundColor(.secondary)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .padding(18)
                    .meterCard(tint: tint, fillOpacity: 0.12, strokeOpacity: 0.18)
            } else {
                ForEach(chargedDevices) { chargedDevice in
                    NavigationLink(destination: ChargedDeviceDetailView(chargedDeviceID: chargedDevice.id)) {
                        ChargedDeviceSidebarCardView(chargedDevice: chargedDevice)
                    }
                    .buttonStyle(.plain)
                }
            }
        }
    }

    private var headerView: some View {
        HStack(alignment: .firstTextBaseline, spacing: 10) {
            Text(title)
                .font(.headline)
            Spacer()
            Button(action: onAdd) {
                Image(systemName: "plus.circle.fill")
                    .font(.body.weight(.semibold))
                    .foregroundColor(tint)
            }
            .buttonStyle(.plain)
            Text("\(chargedDevices.count)")
                .font(.caption.weight(.bold))
                .padding(.horizontal, 10)
                .padding(.vertical, 6)
                .meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24, cornerRadius: 999)
        }
    }
}

private struct ChargedDeviceSidebarCardView: View {
    let chargedDevice: ChargedDeviceSummary

    var body: some View {
        HStack(alignment: .top, spacing: 12) {
            ChargedDeviceQRCodeView(qrIdentifier: chargedDevice.qrIdentifier, side: 54)

            VStack(alignment: .leading, spacing: 6) {
                HStack {
                    Label(chargedDevice.name, systemImage: chargedDevice.identitySymbolName)
                        .font(.headline)
                    if chargedDevice.activeSession != nil {
                        Spacer()
                        Text("Live")
                            .font(.caption.weight(.bold))
                            .foregroundColor(.green)
                    }
                }

                Text(chargedDevice.identityTitle)
                    .font(.caption.weight(.semibold))
                    .foregroundColor(.secondary)

                if chargedDevice.isCharger {
                    if let chargerMaximumPowerWatts = chargedDevice.chargerMaximumPowerWatts {
                        Text("Max power: \(chargerMaximumPowerWatts.format(decimalDigits: 2)) W")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    } else {
                        Text("Wireless charger")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                } else {
                    Text(chargedDevice.supportedChargingModes.map(\.title).joined(separator: " + "))
                        .font(.caption2)
                        .foregroundColor(.secondary)

                    if let estimatedCapacityWh = chargedDevice.estimatedBatteryCapacityWh {
                        Text("Capacity: \(estimatedCapacityWh.format(decimalDigits: 2)) Wh")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    } else {
                        Text("Capacity: learning")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                }
            }
        }
        .padding(.vertical, 4)
    }
}