Add accounts management UI: AccountCardView, AccountsSummaryView, and AccountsListView. Update Dashboard with accounts section
This commit is contained in:
parent
a434d46b18
commit
c3f0a87841
5 changed files with 227 additions and 6 deletions
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
54
Coinly/Features/Accounts/AccountsListView.swift
Normal file
54
Coinly/Features/Accounts/AccountsListView.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
83
Coinly/UI/Components/AccountCardView.swift
Normal file
83
Coinly/UI/Components/AccountCardView.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
67
Coinly/UI/Components/AccountsSummaryView.swift
Normal file
67
Coinly/UI/Components/AccountsSummaryView.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue