better overview design in dark mode

This commit is contained in:
Stefan Lange-Hegermann
2025-11-07 21:11:59 +01:00
parent b11d627fdb
commit 8da6987f32
7 changed files with 92 additions and 32 deletions

View File

@@ -107,6 +107,10 @@
"bom.quantity.count.badge" = "%d×";
"bom.quantity.length.badge" = "%1$.1f %2$@";
"bom.quantity.length.badge.with.spec" = "%1$.1f %2$@ · %3$@";
"bom.quantity.fuse.badge" = "%1$d× · %2$d A";
"bom.quantity.terminal.badge" = "%1$d× · %2$@";
"bom.quantity.cable.badge" = "%1$.1f %2$@ · %3$@";
"bom.quantity.single.badge" = "1× • %@";
"cable.pro.privacy.label" = "Privacy";
"cable.pro.privacy.url" = "https://voltplan.app/privacy";
"cable.pro.terms.label" = "Terms";

View File

@@ -310,7 +310,7 @@ struct SystemOverviewView: View {
.frame(maxWidth: .infinity, alignment: .leading)
.background(
RoundedRectangle(cornerRadius: 20, style: .continuous)
.fill(Color(.systemBackground))
.fill(Color(.tertiarySystemBackground))
)
} else {
Button {
@@ -386,7 +386,7 @@ struct SystemOverviewView: View {
.frame(maxWidth: .infinity, alignment: .leading)
.background(
RoundedRectangle(cornerRadius: 20, style: .continuous)
.fill(Color(.systemBackground))
.fill(Color(.tertiarySystemBackground))
)
}
.buttonStyle(.plain)
@@ -477,7 +477,7 @@ struct SystemOverviewView: View {
.frame(maxWidth: .infinity, alignment: .leading)
.background(
RoundedRectangle(cornerRadius: 20, style: .continuous)
.fill(Color(.systemBackground))
.fill(Color(.tertiarySystemBackground))
)
}
.buttonStyle(.plain)
@@ -560,7 +560,7 @@ struct SystemOverviewView: View {
.frame(maxWidth: .infinity, alignment: .leading)
.background(
RoundedRectangle(cornerRadius: 20, style: .continuous)
.fill(Color(.systemBackground))
.fill(Color(.tertiarySystemBackground))
)
}
.buttonStyle(.plain)
@@ -743,21 +743,47 @@ struct SystemOverviewView: View {
}
private var completedBOMItemCount: Int {
settledLoads.reduce(0) { result, load in
let loadCount = settledLoads.reduce(0) { result, load in
let uniqueItems = Set(load.bomCompletedItemIDs)
let cappedCount = min(uniqueItems.count, Self.bomItemsPerLoad)
return result + cappedCount
}
let batteryCount = settledBatteries.reduce(0) { result, battery in
let uniqueItems = Set(battery.bomCompletedItemIDs)
let cappedCount = min(uniqueItems.count, Self.bomItemsPerBattery)
return result + cappedCount
}
let chargerCount = settledChargers.reduce(0) { result, charger in
let uniqueItems = Set(charger.bomCompletedItemIDs)
let cappedCount = min(uniqueItems.count, Self.bomItemsPerCharger)
return result + cappedCount
}
return loadCount + batteryCount + chargerCount
}
private var bomItemsCount: Int {
settledLoads.isEmpty ? 0 : settledLoads.count * Self.bomItemsPerLoad
let loadItems = settledLoads.count * Self.bomItemsPerLoad
let batteryItems = settledBatteries.count * Self.bomItemsPerBattery
let chargerItems = settledChargers.count * Self.bomItemsPerCharger
let total = loadItems + batteryItems + chargerItems
return total
}
private var settledLoads: [SavedLoad] {
loads.filter { $0.crossSection > 0 && $0.length > 0 }
}
private var settledBatteries: [SavedBattery] {
batteries.filter { $0.system == system }
}
private var settledChargers: [SavedCharger] {
chargers.filter { $0.system == system }
}
private func progressBar(progress: CGFloat?, tint: Color) -> some View {
RoundedRectangle(cornerRadius: 3, style: .continuous)
.fill(Color(.tertiarySystemFill))
@@ -1350,6 +1376,8 @@ struct SystemOverviewView: View {
private static let fallbackGoalHours: Double = 4
private static let bomItemsPerLoad = 5
private static let bomItemsPerBattery = 1
private static let bomItemsPerCharger = 1
private enum BatteryWarning {
case voltage(count: Int)

View File

@@ -165,26 +165,46 @@ struct SystemBillOfMaterialsView: View {
if let scale = quantityScale {
guard let unit = quantifiedDetailContext else { return nil }
let value = Double(quantity) / scale
if let spec = quantifiedDetailSecondaryContext {
let format = NSLocalizedString(
"bom.quantity.length.badge.with.spec",
comment: "Badge text for total cable length including cross section"
)
return String(format: format, locale: Locale.current, value, unit, spec)
} else {
let format = NSLocalizedString(
"bom.quantity.length.badge",
comment: "Badge text for total cable length"
)
return String(format: format, locale: Locale.current, value, unit)
}
let format = NSLocalizedString(
"bom.quantity.cable.badge",
comment: "Metric text for total cable length including cross section"
)
return String(format: format, locale: Locale.current, value, unit, quantifiedDetailSecondaryContext ?? "")
} else if quantity > 1 {
if let fuseRating = quantifiedDetailSecondaryContext, let amps = Int(fuseRating) {
let format = NSLocalizedString(
"bom.quantity.fuse.badge",
comment: "Metric text for consolidated fuses"
)
return String(format: format, quantity, amps)
}
if let gauge = quantifiedDetailContext {
let format = NSLocalizedString(
"bom.quantity.terminal.badge",
comment: "Metric text for consolidated terminals"
)
return String(format: format, quantity, gauge)
}
let format = NSLocalizedString(
"bom.quantity.count.badge",
comment: "Badge text for quantity counts"
comment: "Metric text for counted items"
)
return String(format: format, quantity)
}
if let fuseRating = quantifiedDetailSecondaryContext, let amps = Int(fuseRating) {
let format = NSLocalizedString(
"bom.quantity.fuse.badge",
comment: "Metric text for consolidated fuses"
)
return String(format: format, 1, amps)
}
if let gauge = quantifiedDetailContext, !gauge.isEmpty {
let format = NSLocalizedString(
"bom.quantity.single.badge",
comment: "Metric text when quantity is one but should be explicit"
)
return String(format: format, gauge)
}
return nil
}
@@ -441,15 +461,6 @@ struct SystemBillOfMaterialsView: View {
.foregroundColor(.accentColor)
}
if item.isPrimaryComponent {
Text(String(localized: "component.fallback.name", comment: "Tag label marking an item as the component itself"))
.font(.caption2.weight(.medium))
.foregroundColor(.accentColor)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(Color.accentColor.opacity(0.15), in: Capsule())
}
if shouldShowDetail(for: item) {
Text(item.detail)
.font(.subheadline)
@@ -647,6 +658,7 @@ struct SystemBillOfMaterialsView: View {
let lengthQuantity = Int((max(lengthValue, 0) * 100).rounded())
let redCableMergeKey = "cable.red::\(crossSectionLabel)::\(unitSystem.lengthUnit)"
let blackCableMergeKey = "cable.black::\(crossSectionLabel)::\(unitSystem.lengthUnit)"
let fuseMergeKey = "fuse::\(fuseRating)"
let items: [Item] = [
Item(
@@ -712,9 +724,9 @@ struct SystemBillOfMaterialsView: View {
components: [component],
category: .fuses,
quantity: 1,
mergeKey: nil,
mergeKey: fuseMergeKey,
quantifiedDetailContext: nil,
quantifiedDetailSecondaryContext: nil,
quantifiedDetailSecondaryContext: String(fuseRating),
quantityScale: nil
),
Item(
@@ -730,7 +742,7 @@ struct SystemBillOfMaterialsView: View {
category: .accessories,
quantity: terminalCount,
mergeKey: "terminals::\(crossSectionLabel.lowercased())",
quantifiedDetailContext: nil,
quantifiedDetailContext: crossSectionLabel,
quantifiedDetailSecondaryContext: nil,
quantityScale: nil
)

View File

@@ -167,6 +167,10 @@
"bom.quantity.count.badge" = "%d×";
"bom.quantity.length.badge" = "%1$.1f %2$@";
"bom.quantity.length.badge.with.spec" = "%1$.1f %2$@ · %3$@";
"bom.quantity.fuse.badge" = "%1$d× · %2$d A";
"bom.quantity.terminal.badge" = "%1$d× · %2$@";
"bom.quantity.cable.badge" = "%1$.1f %2$@ · %3$@";
"bom.quantity.single.badge" = "1× • %@";
"cable.pro.privacy.label" = "Datenschutz";
"cable.pro.privacy.url" = "https://voltplan.app/de/datenschutz";
"cable.pro.terms.label" = "Nutzungsbedingungen";

View File

@@ -37,6 +37,10 @@
"bom.quantity.count.badge" = "%d×";
"bom.quantity.length.badge" = "%1$.1f %2$@";
"bom.quantity.length.badge.with.spec" = "%1$.1f %2$@ · %3$@";
"bom.quantity.fuse.badge" = "%1$d× · %2$d A";
"bom.quantity.terminal.badge" = "%1$d× · %2$@";
"bom.quantity.cable.badge" = "%1$.1f %2$@ · %3$@";
"bom.quantity.single.badge" = "1× • %@";
"component.fallback.name" = "Componente";
"default.load.library" = "Carga de la biblioteca";
"default.load.name" = "Mi carga";

View File

@@ -37,6 +37,10 @@
"bom.quantity.count.badge" = "%d×";
"bom.quantity.length.badge" = "%1$.1f %2$@";
"bom.quantity.length.badge.with.spec" = "%1$.1f %2$@ · %3$@";
"bom.quantity.fuse.badge" = "%1$d× · %2$d A";
"bom.quantity.terminal.badge" = "%1$d× · %2$@";
"bom.quantity.cable.badge" = "%1$.1f %2$@ · %3$@";
"bom.quantity.single.badge" = "1× • %@";
"component.fallback.name" = "Composant";
"default.load.library" = "Charge de la bibliothèque";
"default.load.name" = "Ma charge";

View File

@@ -37,6 +37,10 @@
"bom.quantity.count.badge" = "%d×";
"bom.quantity.length.badge" = "%1$.1f %2$@";
"bom.quantity.length.badge.with.spec" = "%1$.1f %2$@ · %3$@";
"bom.quantity.fuse.badge" = "%1$d× · %2$d A";
"bom.quantity.terminal.badge" = "%1$d× · %2$@";
"bom.quantity.cable.badge" = "%1$.1f %2$@ · %3$@";
"bom.quantity.single.badge" = "1× • %@";
"component.fallback.name" = "Component";
"default.load.library" = "Bibliotheeklast";
"default.load.name" = "Mijn last";