WIP: Implement add transactions
Signed-off-by: Billy Brawner <billy@wbrawner.com>
This commit is contained in:
parent
02ca740ad1
commit
3da85c51c3
13 changed files with 231 additions and 18 deletions
|
@ -13,6 +13,7 @@
|
||||||
284102302342D97300EAFA29 /* BudgetListsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2841022F2342D97300EAFA29 /* BudgetListsView.swift */; };
|
284102302342D97300EAFA29 /* BudgetListsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2841022F2342D97300EAFA29 /* BudgetListsView.swift */; };
|
||||||
284102322342E12F00EAFA29 /* CategoryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 284102312342E12F00EAFA29 /* CategoryListView.swift */; };
|
284102322342E12F00EAFA29 /* CategoryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 284102312342E12F00EAFA29 /* CategoryListView.swift */; };
|
||||||
2857EAED233DA30B0026BC83 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2857EAEC233DA30B0026BC83 /* LoadingView.swift */; };
|
2857EAED233DA30B0026BC83 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2857EAEC233DA30B0026BC83 /* LoadingView.swift */; };
|
||||||
|
28A1E95A235006A300CA57FE /* AddTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28A1E959235006A300CA57FE /* AddTransactionView.swift */; };
|
||||||
28AC94EE233C373900BFB70A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28AC94ED233C373900BFB70A /* AppDelegate.swift */; };
|
28AC94EE233C373900BFB70A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28AC94ED233C373900BFB70A /* AppDelegate.swift */; };
|
||||||
28AC94F0233C373900BFB70A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28AC94EF233C373900BFB70A /* SceneDelegate.swift */; };
|
28AC94F0233C373900BFB70A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28AC94EF233C373900BFB70A /* SceneDelegate.swift */; };
|
||||||
28AC94F2233C373900BFB70A /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28AC94F1233C373900BFB70A /* LoginView.swift */; };
|
28AC94F2233C373900BFB70A /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28AC94F1233C373900BFB70A /* LoginView.swift */; };
|
||||||
|
@ -64,6 +65,7 @@
|
||||||
2841022F2342D97300EAFA29 /* BudgetListsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BudgetListsView.swift; sourceTree = "<group>"; };
|
2841022F2342D97300EAFA29 /* BudgetListsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BudgetListsView.swift; sourceTree = "<group>"; };
|
||||||
284102312342E12F00EAFA29 /* CategoryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryListView.swift; sourceTree = "<group>"; };
|
284102312342E12F00EAFA29 /* CategoryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryListView.swift; sourceTree = "<group>"; };
|
||||||
2857EAEC233DA30B0026BC83 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
|
2857EAEC233DA30B0026BC83 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
|
||||||
|
28A1E959235006A300CA57FE /* AddTransactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTransactionView.swift; sourceTree = "<group>"; };
|
||||||
28AC94EA233C373900BFB70A /* Budget.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Budget.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
28AC94EA233C373900BFB70A /* Budget.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Budget.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
28AC94ED233C373900BFB70A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
28AC94ED233C373900BFB70A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
28AC94EF233C373900BFB70A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
28AC94EF233C373900BFB70A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
@ -233,6 +235,7 @@
|
||||||
28FE6B012344331B00D5543E /* TransactionDataStore.swift */,
|
28FE6B012344331B00D5543E /* TransactionDataStore.swift */,
|
||||||
28FE6B03234449DC00D5543E /* TransactionListView.swift */,
|
28FE6B03234449DC00D5543E /* TransactionListView.swift */,
|
||||||
28FE6B0523444A9800D5543E /* TransactionDetailsView.swift */,
|
28FE6B0523444A9800D5543E /* TransactionDetailsView.swift */,
|
||||||
|
28A1E959235006A300CA57FE /* AddTransactionView.swift */,
|
||||||
);
|
);
|
||||||
path = Transaction;
|
path = Transaction;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -389,6 +392,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
28FE6AFE234428BF00D5543E /* DataStoreProvider.swift in Sources */,
|
28FE6AFE234428BF00D5543E /* DataStoreProvider.swift in Sources */,
|
||||||
|
28A1E95A235006A300CA57FE /* AddTransactionView.swift in Sources */,
|
||||||
28AC94EE233C373900BFB70A /* AppDelegate.swift in Sources */,
|
28AC94EE233C373900BFB70A /* AppDelegate.swift in Sources */,
|
||||||
28AC94F0233C373900BFB70A /* SceneDelegate.swift in Sources */,
|
28AC94F0233C373900BFB70A /* SceneDelegate.swift in Sources */,
|
||||||
28FE6AFC23441E4500D5543E /* CategoryRepository.swift in Sources */,
|
28FE6AFC23441E4500D5543E /* CategoryRepository.swift in Sources */,
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
filePath = "Budget/Transaction/TransactionListView.swift"
|
filePath = "Budget/Transaction/TransactionListView.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "52"
|
startingLineNumber = "53"
|
||||||
endingLineNumber = "52"
|
endingLineNumber = "53"
|
||||||
landmarkName = "body"
|
landmarkName = "body"
|
||||||
landmarkType = "24">
|
landmarkType = "24">
|
||||||
<Locations>
|
<Locations>
|
||||||
|
@ -413,8 +413,8 @@
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "23"
|
startingLineNumber = "23"
|
||||||
endingLineNumber = "23"
|
endingLineNumber = "23"
|
||||||
landmarkName = "getTransactions(_:)"
|
landmarkName = "transaction"
|
||||||
landmarkType = "7">
|
landmarkType = "24">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
|
@ -429,8 +429,8 @@
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "22"
|
startingLineNumber = "22"
|
||||||
endingLineNumber = "22"
|
endingLineNumber = "22"
|
||||||
landmarkName = "getTransactions(_:)"
|
landmarkName = "transaction"
|
||||||
landmarkType = "7">
|
landmarkType = "24">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
|
@ -513,5 +513,21 @@
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "64E00C07-F5B8-44C5-A75B-76A8F00496E8"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "Budget/Transaction/AddTransactionView.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "27"
|
||||||
|
endingLineNumber = "27"
|
||||||
|
landmarkName = "stateContent"
|
||||||
|
landmarkType = "24">
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
</Breakpoints>
|
</Breakpoints>
|
||||||
</Bucket>
|
</Bucket>
|
||||||
|
|
|
@ -27,8 +27,8 @@ class DataStoreProvider {
|
||||||
return CategoryDataStore(categoryRepository, budget: budget)
|
return CategoryDataStore(categoryRepository, budget: budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func transactionDataStore(_ category: Category? = nil) -> TransactionDataStore {
|
func transactionDataStore() -> TransactionDataStore {
|
||||||
return TransactionDataStore(transactionRepository, category: category)
|
return TransactionDataStore(transactionRepository)
|
||||||
}
|
}
|
||||||
|
|
||||||
func userDataStore() -> UserDataStore {
|
func userDataStore() -> UserDataStore {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct TabbedBudgetView: View {
|
struct TabbedBudgetView: View {
|
||||||
@ObservedObject var userData: UserDataStore
|
@ObservedObject var userData: UserDataStore
|
||||||
|
@State var isAddingTransaction = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TabView {
|
TabView {
|
||||||
|
@ -20,18 +21,26 @@ struct TabbedBudgetView: View {
|
||||||
leading: NavigationLink(destination: EmptyView()) {
|
leading: NavigationLink(destination: EmptyView()) {
|
||||||
Text("filter")
|
Text("filter")
|
||||||
},
|
},
|
||||||
trailing: NavigationLink(destination: EmptyView().navigationBarTitle("add_transaction")) {
|
trailing: Button(action: {
|
||||||
Text("add")
|
self.isAddingTransaction = true
|
||||||
|
}) {
|
||||||
|
Image(systemName: "plus")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}.tabItem {
|
.sheet(isPresented: $isAddingTransaction, content: {
|
||||||
|
AddTransactionView(self.dataStoreProvider)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.tabItem {
|
||||||
Image(systemName: "dollarsign.circle.fill")
|
Image(systemName: "dollarsign.circle.fill")
|
||||||
Text("transactions")
|
Text("transactions")
|
||||||
}
|
}
|
||||||
|
|
||||||
BudgetListsView(dataStoreProvider).tabItem {
|
BudgetListsView(dataStoreProvider).tabItem {
|
||||||
Image(systemName: "chart.pie.fill")
|
Image(systemName: "chart.pie.fill")
|
||||||
Text("budgets")
|
Text("budgets")
|
||||||
}
|
}
|
||||||
|
|
||||||
Text("Profile here").tabItem {
|
Text("Profile here").tabItem {
|
||||||
Image(systemName: "person.circle.fill")
|
Image(systemName: "person.circle.fill")
|
||||||
Text("profile")
|
Text("profile")
|
||||||
|
|
98
Budget/Transaction/AddTransactionView.swift
Normal file
98
Budget/Transaction/AddTransactionView.swift
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
//
|
||||||
|
// AddTransactionView.swift
|
||||||
|
// Budget
|
||||||
|
//
|
||||||
|
// Created by Billy Brawner on 10/10/19.
|
||||||
|
// Copyright © 2019 William Brawner. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AddTransactionView: View {
|
||||||
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
@State var id: Int? = nil
|
||||||
|
@State var title: String = ""
|
||||||
|
@State var description: String = ""
|
||||||
|
@State var date: Date = Date()
|
||||||
|
@State var amount: String = ""
|
||||||
|
@State var categoryId: Int = 0
|
||||||
|
@State var type: TransactionType = .expense
|
||||||
|
@State var budgetId: Int = 0
|
||||||
|
let createdBy: Int
|
||||||
|
|
||||||
|
var stateContent: AnyView {
|
||||||
|
switch transactionDataStore.transaction {
|
||||||
|
case .success(_):
|
||||||
|
// TODO: Figure out how to pass transaction up to previous view
|
||||||
|
self.presentationMode.wrappedValue.dismiss()
|
||||||
|
return AnyView(EmptyView())
|
||||||
|
|
||||||
|
case .failure(.loading):
|
||||||
|
return AnyView(VStack {
|
||||||
|
ActivityIndicator(isAnimating: .constant(true), style: .large)
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
// TODO: Handle each network failure type
|
||||||
|
return AnyView(Form {
|
||||||
|
Section {
|
||||||
|
TextField("prompt_name", text: self.$title)
|
||||||
|
TextField("prompt_description", text: self.$description)
|
||||||
|
DatePicker(selection: self.$date, label: { Text("prompt_date") })
|
||||||
|
TextField("prompt_amount", text: self.$amount)
|
||||||
|
.keyboardType(.decimalPad)
|
||||||
|
Picker("prompt_type", selection: self.$type) {
|
||||||
|
ForEach(TransactionType.allCases) { type in
|
||||||
|
Text(type.localizedKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Figure out how to load budgets dynamically
|
||||||
|
Picker("prompt_budget", selection: self.$type) {
|
||||||
|
ForEach(TransactionType.allCases) { type in
|
||||||
|
Text(type.localizedKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Figure out how to load categories dynamically
|
||||||
|
Picker("prompt_category", selection: self.$type) {
|
||||||
|
ForEach(TransactionType.allCases) { type in
|
||||||
|
Text(type.localizedKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
stateContent
|
||||||
|
.navigationBarTitle("add_transaction")
|
||||||
|
.navigationBarItems(leading: Button("cancel") {
|
||||||
|
self.presentationMode.wrappedValue.dismiss()
|
||||||
|
}, trailing: Button("save") {
|
||||||
|
self.transactionDataStore.createTransaction(Transaction(
|
||||||
|
id: self.id,
|
||||||
|
title: self.title,
|
||||||
|
description: self.description,
|
||||||
|
date: self.date,
|
||||||
|
amount: Int(Double(self.amount) ?? 0.0 * 100.0),
|
||||||
|
categoryId: self.categoryId,
|
||||||
|
expense: self.type == TransactionType.expense,
|
||||||
|
createdBy: self.createdBy,
|
||||||
|
budgetId: self.budgetId
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ObservedObject var transactionDataStore: TransactionDataStore
|
||||||
|
init(_ dataStoreProvider: DataStoreProvider) {
|
||||||
|
self.transactionDataStore = dataStoreProvider.transactionDataStore()
|
||||||
|
self.createdBy = try! dataStoreProvider.userDataStore().currentUser.get().id!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//struct AddTransactionView_Previews: PreviewProvider {
|
||||||
|
// static var previews: some View {
|
||||||
|
// AddTransactionView()
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
struct Transaction: Identifiable, Codable {
|
struct Transaction: Identifiable, Codable {
|
||||||
let id: Int?
|
let id: Int?
|
||||||
|
@ -15,7 +16,25 @@ struct Transaction: Identifiable, Codable {
|
||||||
let date: Date
|
let date: Date
|
||||||
let amount: Int
|
let amount: Int
|
||||||
let categoryId: Int?
|
let categoryId: Int?
|
||||||
let expense: Bool = true
|
let expense: Bool
|
||||||
let createdBy: Int
|
let createdBy: Int
|
||||||
let budgetId: Int
|
let budgetId: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TransactionType: Int, CaseIterable, Identifiable, Hashable {
|
||||||
|
case expense
|
||||||
|
case income
|
||||||
|
|
||||||
|
var localizedKey: LocalizedStringKey {
|
||||||
|
var key: String
|
||||||
|
switch self {
|
||||||
|
case .expense:
|
||||||
|
key = "type_expense"
|
||||||
|
case .income:
|
||||||
|
key = "type_income"
|
||||||
|
}
|
||||||
|
return LocalizedStringKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
var id: TransactionType { self }
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,12 @@ class TransactionDataStore: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var transaction: Result<Transaction, NetworkError> = .failure(.unknown) {
|
||||||
|
didSet {
|
||||||
|
self.objectWillChange.send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getTransactions(_ category: Category? = nil) {
|
func getTransactions(_ category: Category? = nil) {
|
||||||
self.transactions = .failure(.loading)
|
self.transactions = .failure(.loading)
|
||||||
|
|
||||||
|
@ -37,10 +43,26 @@ class TransactionDataStore: ObservableObject {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createTransaction(_ transaction: Transaction) {
|
||||||
|
self.transaction = .failure(.loading)
|
||||||
|
|
||||||
|
_ = self.transactionRepository.createTransaction(transaction)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink(receiveCompletion: { (completion) in
|
||||||
|
switch completion {
|
||||||
|
case .finished:
|
||||||
|
return
|
||||||
|
case .failure(let error):
|
||||||
|
self.transaction = .failure(error)
|
||||||
|
}
|
||||||
|
}, receiveValue: { (transaction) in
|
||||||
|
self.transaction = .success(transaction)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let objectWillChange = ObservableObjectPublisher()
|
let objectWillChange = ObservableObjectPublisher()
|
||||||
private let transactionRepository: TransactionRepository
|
private let transactionRepository: TransactionRepository
|
||||||
init(_ transactionRepository: TransactionRepository, category: Category? = nil) {
|
init(_ transactionRepository: TransactionRepository) {
|
||||||
self.transactionRepository = transactionRepository
|
self.transactionRepository = transactionRepository
|
||||||
self.getTransactions(category)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,31 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct TransactionDetailsView: View {
|
struct TransactionDetailsView: View {
|
||||||
|
@State var title: String = ""
|
||||||
|
@State var description: String? = nil
|
||||||
|
@State var date: Date = Date()
|
||||||
|
@State var amount: Int = 0
|
||||||
|
@State var category: Category? = nil
|
||||||
|
@State var expense: Bool = true
|
||||||
|
@State var createdBy: User? = nil
|
||||||
|
@State var budget: Budget? = nil
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(/*@START_MENU_TOKEN@*/"Hello World!"/*@END_MENU_TOKEN@*/)
|
List {
|
||||||
|
TextField("prompt_title", text: self.$title)
|
||||||
|
// DatePicker(
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ dataStoreProvider: DataStoreProvider, transaction: Transaction) {
|
init(_ dataStoreProvider: DataStoreProvider, transaction: Transaction) {
|
||||||
|
// self.title = transaction.title
|
||||||
|
// self.description = transaction.description
|
||||||
|
// self.date = transaction.date
|
||||||
|
// self.amount = transaction.amount
|
||||||
|
// self.category = transaction.category
|
||||||
|
// self.expense = transaction.expense
|
||||||
|
// self.createdBy = transaction.createdBy
|
||||||
|
// self.budget = transaction.budget
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ struct TransactionListView: View {
|
||||||
let dataStoreProvider: DataStoreProvider
|
let dataStoreProvider: DataStoreProvider
|
||||||
init(_ dataStoreProvider: DataStoreProvider, category: Category? = nil) {
|
init(_ dataStoreProvider: DataStoreProvider, category: Category? = nil) {
|
||||||
self.dataStoreProvider = dataStoreProvider
|
self.dataStoreProvider = dataStoreProvider
|
||||||
self.transactionDataStore = dataStoreProvider.transactionDataStore(category)
|
self.transactionDataStore = dataStoreProvider.transactionDataStore()
|
||||||
|
self.transactionDataStore.getTransactions(category)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,4 +19,8 @@ class TransactionRepository {
|
||||||
func getTransactions(categoryIds: [Int]? = nil, from: Date? = nil, count: Int? = nil, page: Int? = nil) -> AnyPublisher<[Transaction], NetworkError> {
|
func getTransactions(categoryIds: [Int]? = nil, from: Date? = nil, count: Int? = nil, page: Int? = nil) -> AnyPublisher<[Transaction], NetworkError> {
|
||||||
return apiService.getTransactions(categoryIds: categoryIds, from: from, count: count, page: page)
|
return apiService.getTransactions(categoryIds: categoryIds, from: from, count: count, page: page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createTransaction(_ transaction: Transaction) -> AnyPublisher<Transaction, NetworkError> {
|
||||||
|
return apiService.newTransaction(transaction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,18 @@
|
||||||
// MARK: Generic
|
// MARK: Generic
|
||||||
"add" = "Add";
|
"add" = "Add";
|
||||||
"filter" = "Filter";
|
"filter" = "Filter";
|
||||||
|
"save" = "Save";
|
||||||
|
"cancel" = "Cancel";
|
||||||
"loading_default" = "Loading...";
|
"loading_default" = "Loading...";
|
||||||
|
"prompt_name" = "Name";
|
||||||
|
"prompt_description" = "Description";
|
||||||
|
"prompt_amount" = "Amount";
|
||||||
|
"prompt_date" = "Date";
|
||||||
|
"prompt_category" = "Category";
|
||||||
|
"prompt_budget" = "Budget";
|
||||||
|
"prompt_type" = "Type";
|
||||||
|
"type_income" = "Income";
|
||||||
|
"type_expense" = "Expense";
|
||||||
|
|
||||||
// MARK: Login
|
// MARK: Login
|
||||||
"info_login" = "Login to start managing your budget";
|
"info_login" = "Login to start managing your budget";
|
||||||
|
|
|
@ -9,7 +9,18 @@
|
||||||
// MARK: Generic
|
// MARK: Generic
|
||||||
"add" = "Agregar";
|
"add" = "Agregar";
|
||||||
"filter" = "Filtrar";
|
"filter" = "Filtrar";
|
||||||
|
"save" = "Guardar";
|
||||||
|
"cancel" = "Cancelar";
|
||||||
"loading_default" = "Cargando...";
|
"loading_default" = "Cargando...";
|
||||||
|
"prompt_name" = "Nombre";
|
||||||
|
"prompt_description" = "Descripción";
|
||||||
|
"prompt_amount" = "Monto";
|
||||||
|
"prompt_date" = "Fecha";
|
||||||
|
"prompt_category" = "Categoría";
|
||||||
|
"prompt_budget" = "Presupuesto";
|
||||||
|
"prompt_type" = "Tipo";
|
||||||
|
"type_income" = "Ingreso";
|
||||||
|
"type_expense" = "Gasto";
|
||||||
|
|
||||||
// MARK: Login
|
// MARK: Login
|
||||||
"info_login" = "Inicia sesión para empezar a manejar su presupuseto";
|
"info_login" = "Inicia sesión para empezar a manejar su presupuseto";
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
@testable import Budget
|
|
||||||
|
|
||||||
class BudgetTests: XCTestCase {
|
class BudgetTests: XCTestCase {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue