diff --git a/PulseHealth/Views/Savings/SavingsView.swift b/PulseHealth/Views/Savings/SavingsView.swift index 3ffcfca..26ee184 100644 --- a/PulseHealth/Views/Savings/SavingsView.swift +++ b/PulseHealth/Views/Savings/SavingsView.swift @@ -625,3 +625,56 @@ struct AddSavingsTransactionView: View { } } } + +// MARK: - SavingsCategoryCard + +struct SavingsCategoryCard: View { + let category: SavingsCategory + + var body: some View { + HStack(spacing: 14) { + ZStack { + Circle() + .fill(Color(hex: category.colorHex).opacity(0.15)) + .frame(width: 46, height: 46) + Image(systemName: category.icon) + .foregroundColor(Color(hex: category.colorHex)) + .font(.title3) + } + VStack(alignment: .leading, spacing: 4) { + HStack(spacing: 4) { + Text(category.typeEmoji) + Text(category.name) + .font(.callout.bold()) + .foregroundColor(.white) + } + Text(category.typeLabel) + .font(.caption2) + .foregroundColor(Color(hex: "8888aa")) + } + Spacer() + VStack(alignment: .trailing, spacing: 4) { + Text(formatAmt(category.currentAmount ?? 0)) + .font(.callout.bold()) + .foregroundColor(Color(hex: category.colorHex)) + if let target = category.targetAmount, target > 0 { + let progress = min((category.currentAmount ?? 0) / target, 1.0) + Text(String(format: "%.0f%%", progress * 100)) + .font(.caption2) + .foregroundColor(Color(hex: "8888aa")) + } + } + } + .padding(14) + .background(RoundedRectangle(cornerRadius: 14).fill(Color.white.opacity(0.04))) + .overlay( + RoundedRectangle(cornerRadius: 14) + .stroke(Color(hex: category.colorHex).opacity(0.15), lineWidth: 1) + ) + .padding(.horizontal) + } + + func formatAmt(_ v: Double) -> String { + v >= 1_000_000 ? String(format: "%.2f млн ₽", v / 1_000_000) : String(format: "%.0f ₽", v) + } +}