Add accounts management UI: AccountCardView, AccountsSummaryView, and AccountsListView. Update Dashboard with accounts section

This commit is contained in:
“SamoilenkoVadym” 2025-03-02 19:57:22 +00:00
parent a434d46b18
commit c3f0a87841
5 changed files with 227 additions and 6 deletions

View file

@ -2,14 +2,18 @@ import SwiftUI
struct ContentView: View {
@StateObject private var transactionsStore = TransactionsStore()
@StateObject private var accountsStore = AccountsStore()
@StateObject private var settings = AppSettings.shared
var body: some View {
TabView {
DashboardView(store: transactionsStore)
.tabItem {
Label("Dashboard", systemImage: "chart.pie.fill")
}
DashboardView(
store: transactionsStore,
accountsStore: accountsStore
)
.tabItem {
Label("Dashboard", systemImage: "chart.pie.fill")
}
TransactionsView(store: transactionsStore)
.tabItem {
@ -24,3 +28,9 @@ struct ContentView: View {
.environmentObject(settings)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

View file

@ -0,0 +1,54 @@
//
// AccountsListView.swift
// Coinly
//
// Created by Vadym Samoilenko on 02/03/2025.
//
import SwiftUI
struct AccountsListView: View {
@Environment(\.dismiss) private var dismiss
@ObservedObject var store: AccountsStore
@State private var showingAddAccount = false
var body: some View {
NavigationView {
List {
ForEach(AccountType.allCases, id: \.self) { type in
Section(type.rawValue) {
ForEach(store.getAccounts(of: type)) { account in
AccountCardView(account: account)
}
}
}
}
.listStyle(InsetGroupedListStyle())
.navigationTitle("Accounts")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Close") {
dismiss()
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
showingAddAccount = true
} label: {
Image(systemName: "plus")
}
}
}
}
}
}
struct AccountsListView_Previews: PreviewProvider {
static var previews: some View {
AccountsListView(store: AccountsStore())
.environmentObject(AppSettings.shared)
}
}

View file

@ -2,6 +2,7 @@ import SwiftUI
struct DashboardView: View {
@ObservedObject var store: TransactionsStore
@ObservedObject var accountsStore: AccountsStore
@EnvironmentObject private var settings: AppSettings
private var totalBalance: Double {
@ -58,6 +59,9 @@ struct DashboardView: View {
.cornerRadius(12)
.shadow(radius: 2)
// Accounts Summary
AccountsSummaryView(accountsStore: accountsStore)
// Income/Expense Summary
HStack(spacing: 16) {
// Income Card
@ -157,7 +161,10 @@ struct DashboardView: View {
struct DashboardView_Previews: PreviewProvider {
static var previews: some View {
DashboardView(store: TransactionsStore())
.environmentObject(AppSettings.shared)
DashboardView(
store: TransactionsStore(),
accountsStore: AccountsStore()
)
.environmentObject(AppSettings.shared)
}
}

View file

@ -0,0 +1,83 @@
//
// AccountCardView.swift
// Coinly
//
// Created by Vadym Samoilenko on 02/03/2025.
//
import SwiftUI
struct AccountCardView: View {
let account: AccountModel
@EnvironmentObject private var settings: AppSettings
private var accountIcon: String {
account.type.icon
}
private var accountColor: Color {
switch account.type {
case .wallet: return .blue
case .bankAccount: return .green
case .creditCard: return .purple
case .deposit: return .orange
case .debt: return .red
}
}
var body: some View {
VStack(alignment: .leading, spacing: 12) {
// Header
HStack {
Image(systemName: accountIcon)
.font(.title2)
.foregroundColor(accountColor)
Text(account.name)
.font(.headline)
Spacer()
Text(account.currency.symbol)
.font(.subheadline)
.foregroundColor(.gray)
}
// Balance
Text(account.balance.formatAsCurrency())
.font(.title2)
.fontWeight(.bold)
// Additional Info
if let availableCredit = account.availableCredit {
Text("Available: \(availableCredit.formatAsCurrency())")
.font(.caption)
.foregroundColor(.gray)
}
if account.isOverdue {
Label("Overdue", systemImage: "exclamationmark.circle.fill")
.font(.caption)
.foregroundColor(.red)
}
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(radius: 2)
}
}
struct AccountCardView_Previews: PreviewProvider {
static var previews: some View {
Group {
AccountCardView(account: AccountModel.sampleData[0])
AccountCardView(account: AccountModel.sampleData[2])
}
.padding()
.background(Color(.systemGroupedBackground))
.environmentObject(AppSettings.shared)
.previewLayout(.sizeThatFits)
}
}

View file

@ -0,0 +1,67 @@
//
// AccountsSummaryView.swift
// Coinly
//
// Created by Vadym Samoilenko on 02/03/2025.
//
import SwiftUI
struct AccountsSummaryView: View {
@ObservedObject var accountsStore: AccountsStore
@EnvironmentObject private var settings: AppSettings
@State private var showingAccountsList = false
private var totalBalance: Double {
accountsStore.totalBalance(in: settings.currency)
}
var body: some View {
VStack(spacing: 16) {
// Header with total balance
VStack(spacing: 8) {
Text("Total Assets")
.font(.subheadline)
.foregroundColor(.gray)
Text(totalBalance.formatAsCurrency())
.font(.title2)
.fontWeight(.bold)
}
// Recent accounts preview
VStack(spacing: 12) {
ForEach(Array(accountsStore.accounts.prefix(2))) { account in
AccountCardView(account: account)
}
}
// Show all button
Button(action: {
showingAccountsList = true
}) {
Text("Show All Accounts")
.font(.headline)
.foregroundColor(.blue)
}
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(radius: 2)
.sheet(isPresented: $showingAccountsList) {
AccountsListView(store: accountsStore)
}
}
}
struct AccountsSummaryView_Previews: PreviewProvider {
static var previews: some View {
AccountsSummaryView(accountsStore: AccountsStore())
.environmentObject(AppSettings.shared)
.padding()
.background(Color(.systemGroupedBackground))
.previewLayout(.sizeThatFits)
}
}