v2.0.2 — Show spent, limit, and balance in extra usage section
This commit is contained in:
@@ -493,6 +493,12 @@ struct ExtraUsageRow: View {
|
|||||||
|
|
||||||
var pct: Double { min(100, max(0, extra.utilization ?? 0)) }
|
var pct: Double { min(100, max(0, extra.utilization ?? 0)) }
|
||||||
var color: Color { pct > 80 ? .red : pct > 50 ? .orange : .green }
|
var color: Color { pct > 80 ? .red : pct > 50 ? .orange : .green }
|
||||||
|
var cur: String { extra.currency ?? "" }
|
||||||
|
|
||||||
|
func fmt(_ cents: Double?) -> String {
|
||||||
|
guard let cents else { return "—" }
|
||||||
|
return String(format: "%.2f", cents / 100)
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
@@ -503,18 +509,13 @@ struct ExtraUsageRow: View {
|
|||||||
Text("Extra Usage Credits")
|
Text("Extra Usage Credits")
|
||||||
.font(.system(size: 12, weight: .semibold))
|
.font(.system(size: 12, weight: .semibold))
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
Spacer()
|
}
|
||||||
Group {
|
VStack(spacing: 4) {
|
||||||
let spent = String(format: "%.2f", (extra.usedCredits ?? 0) / 100)
|
ExtraUsageLine(label: "Spent", value: "\(cur) \(fmt(extra.usedCredits))", color: color)
|
||||||
let currency = extra.currency ?? ""
|
ExtraUsageLine(label: "Limit", value: extra.monthlyLimit != nil ? "\(cur) \(fmt(extra.monthlyLimit))" : "Unlimited", color: .secondary)
|
||||||
if let limit = extra.monthlyLimit {
|
if extra.currentBalance != nil {
|
||||||
Text("\(currency) \(spent) / \(String(format: "%.2f", limit / 100))")
|
ExtraUsageLine(label: "Balance", value: "\(cur) \(fmt(extra.currentBalance))", color: .primary)
|
||||||
} else {
|
|
||||||
Text("\(currency) \(spent) / Unlimited")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.font(.system(size: 11.5, weight: .medium).monospacedDigit())
|
|
||||||
.foregroundColor(color)
|
|
||||||
}
|
}
|
||||||
if extra.monthlyLimit != nil {
|
if extra.monthlyLimit != nil {
|
||||||
ProgressBar(value: pct / 100, color: color)
|
ProgressBar(value: pct / 100, color: color)
|
||||||
@@ -528,6 +529,23 @@ struct ExtraUsageRow: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ExtraUsageLine: View {
|
||||||
|
let label: String
|
||||||
|
let value: String
|
||||||
|
let color: Color
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Text(label)
|
||||||
|
.font(.system(size: 11))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Spacer()
|
||||||
|
Text(value)
|
||||||
|
.font(.system(size: 11.5, weight: .medium).monospacedDigit())
|
||||||
|
.foregroundColor(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Settings View
|
// MARK: - Settings View
|
||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
|
|||||||
@@ -85,22 +85,28 @@ struct ExtraUsage: Codable {
|
|||||||
let isEnabled: Bool
|
let isEnabled: Bool
|
||||||
let monthlyLimit: Double?
|
let monthlyLimit: Double?
|
||||||
let usedCredits: Double?
|
let usedCredits: Double?
|
||||||
|
let currentBalance: Double?
|
||||||
let utilization: Double?
|
let utilization: Double?
|
||||||
let currency: String?
|
let currency: String?
|
||||||
|
let resetsAt: String?
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case isEnabled = "is_enabled"
|
case isEnabled = "is_enabled"
|
||||||
case monthlyLimit = "monthly_limit"
|
case monthlyLimit = "monthly_limit"
|
||||||
case usedCredits = "used_credits"
|
case usedCredits = "used_credits"
|
||||||
|
case currentBalance = "current_balance"
|
||||||
case utilization
|
case utilization
|
||||||
case currency
|
case currency
|
||||||
|
case resetsAt = "resets_at"
|
||||||
}
|
}
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
isEnabled = (try? c.decodeIfPresent(Bool.self, forKey: .isEnabled)) ?? false
|
isEnabled = (try? c.decodeIfPresent(Bool.self, forKey: .isEnabled)) ?? false
|
||||||
monthlyLimit = try? c.decodeIfPresent(Double.self, forKey: .monthlyLimit)
|
monthlyLimit = try? c.decodeIfPresent(Double.self, forKey: .monthlyLimit)
|
||||||
usedCredits = try? c.decodeIfPresent(Double.self, forKey: .usedCredits)
|
usedCredits = try? c.decodeIfPresent(Double.self, forKey: .usedCredits)
|
||||||
utilization = try? c.decodeIfPresent(Double.self, forKey: .utilization)
|
currentBalance = try? c.decodeIfPresent(Double.self, forKey: .currentBalance)
|
||||||
currency = try? c.decodeIfPresent(String.self, forKey: .currency)
|
utilization = try? c.decodeIfPresent(Double.self, forKey: .utilization)
|
||||||
|
currency = try? c.decodeIfPresent(String.self, forKey: .currency)
|
||||||
|
resetsAt = try? c.decodeIfPresent(String.self, forKey: .resetsAt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user