Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f1260f0

Browse files
committedJan 16, 2025·
Added export tab & options sheet &share sheet
1 parent e0508f3 commit f1260f0

9 files changed

+143
-5
lines changed
 

‎Data/Data/Repository/CommentRepository.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public class CommentRepository {
9494
let payerName = (user.id == transaction.payerId && memberId == transaction.payerId) ?
9595
(user.id == transaction.addedBy ? "You" : "you") :
9696
(memberId == transaction.payerId) ? "you" : members.payer.nameWithLastInitial
97-
97+
9898
let receiverName = (memberId == transaction.receiverId) ? "you" : (memberId == transaction.receiverId) ? "you" : members.receiver.nameWithLastInitial
9999

100100
context = ActivityLogContext(group: group, transaction: transaction, comment: comment,

‎Data/Data/Repository/ExpenseRepository.swift

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ public class ExpenseRepository: ObservableObject {
164164
return try await store.fetchExpensesBy(groupId: groupId, limit: limit, lastDocument: lastDocument)
165165
}
166166

167+
public func fetchExpenses(groupId: String, startDate: Date?, endDate: Date) async throws -> [Expense] {
168+
try await store.fetchExpenses(groupId: groupId, startDate: startDate, endDate: endDate)
169+
}
170+
167171
public func fetchExpenseBy(groupId: String, expenseId: String) async throws -> Expense {
168172
return try await store.fetchExpenseBy(groupId: groupId, expenseId: expenseId)
169173
}

‎Data/Data/Repository/TransactionRepository.swift

+4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ public class TransactionRepository: ObservableObject {
155155
try await store.fetchTransactionsBy(groupId: groupId, limit: limit, lastDocument: lastDocument)
156156
}
157157

158+
public func fetchTransactions(groupId: String, startDate: Date?, endDate: Date) async throws -> [Transactions] {
159+
try await store.fetchTransactions(groupId: groupId, startDate: startDate, endDate: endDate)
160+
}
161+
158162
public func fetchTransactionBy(groupId: String, transactionId: String) async throws -> Transactions {
159163
try await store.fetchTransactionsBy(groupId: groupId, transactionId: transactionId)
160164
}

‎Data/Data/Store/ExpenseStore.swift

+23
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,29 @@ public class ExpenseStore: ObservableObject {
6060
return (expenses, snapshot.documents.last)
6161
}
6262

63+
func fetchExpenses(groupId: String, startDate: Date?, endDate: Date) async throws -> [Expense] {
64+
if let startDate {
65+
let startTimestamp = Timestamp(date: startDate)
66+
let endTimestamp = Timestamp(date: endDate)
67+
68+
let query = expenseReference(groupId: groupId)
69+
.whereField("is_active", isEqualTo: true)
70+
.whereField("date", isGreaterThanOrEqualTo: startTimestamp)
71+
.whereField("date", isLessThanOrEqualTo: endTimestamp)
72+
73+
let snapshot = try await query.getDocuments(source: .server).documents
74+
75+
return try snapshot.map { document in
76+
try document.data(as: Expense.self)
77+
}
78+
} else {
79+
return try await expenseReference(groupId: groupId)
80+
.whereField("is_active", isEqualTo: true)
81+
.order(by: "date", descending: true)
82+
.getDocuments(as: Expense.self).data
83+
}
84+
}
85+
6386
func fetchExpensesOfAllGroups(userId: String, activeGroupIds: [String], limit: Int,
6487
lastDocument: DocumentSnapshot?) async throws -> (expenses: [Expense], lastDocument: DocumentSnapshot?) {
6588

‎Data/Data/Store/TransactionStore.swift

+23
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,29 @@ public class TransactionStore: ObservableObject {
5656
return (transactions, snapshot.documents.last)
5757
}
5858

59+
func fetchTransactions(groupId: String, startDate: Date?, endDate: Date) async throws -> [Transactions] {
60+
if let startDate {
61+
let startTimestamp = Timestamp(date: startDate)
62+
let endTimestamp = Timestamp(date: endDate)
63+
64+
let query = transactionReference(groupId: groupId)
65+
.whereField("is_active", isEqualTo: true)
66+
.whereField("date", isGreaterThanOrEqualTo: startTimestamp)
67+
.whereField("date", isLessThanOrEqualTo: endTimestamp)
68+
69+
let snapshot = try await query.getDocuments(source: .server).documents
70+
71+
return try snapshot.map { document in
72+
try document.data(as: Transactions.self)
73+
}
74+
} else {
75+
return try await transactionReference(groupId: groupId)
76+
.whereField("is_active", isEqualTo: true)
77+
.order(by: "date", descending: true)
78+
.getDocuments(as: Transactions.self).data
79+
}
80+
}
81+
5982
func fetchTransactionsBy(groupId: String, transactionId: String) async throws -> Transactions {
6083
try await transactionReference(groupId: groupId)
6184
.document(transactionId)

‎Splito/UI/Home/Groups/Group/GroupExpenseListView.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ struct GroupExpenseListView: View {
1919
GeometryReader { geometry in
2020
ScrollViewReader { scrollProxy in
2121
VStack(alignment: .leading, spacing: 0) {
22-
GroupOptionsListView(isSettleUpEnable: (!viewModel.memberOwingAmount.isEmpty && viewModel.group?.members.count ?? 1 > 1),
22+
GroupOptionsListView(showShareSheet: $viewModel.showShareSheet, showExportOptions: $viewModel.showExportOptions,
23+
isSettleUpEnable: (!viewModel.memberOwingAmount.isEmpty && viewModel.group?.members.count ?? 1 > 1),
2324
onSettleUpTap: viewModel.handleSettleUpBtnTap,
2425
onTransactionsTap: viewModel.handleTransactionsBtnTap,
2526
onBalanceTap: viewModel.handleBalancesBtnTap,
26-
onTotalsTap: viewModel.handleTotalBtnTap)
27+
onTotalsTap: viewModel.handleTotalBtnTap,
28+
onExportTap: { exportOption, completion in
29+
viewModel.handleExportTap(exportOption: exportOption, completion: completion)
30+
})
2731

2832
if viewModel.showSearchBar {
2933
SearchBar(text: $viewModel.searchedExpense, isFocused: isFocused, placeholder: "Search expenses")

‎Splito/UI/Home/Groups/Group/GroupHomeView.swift

+46-1
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,16 @@ struct GroupHomeView: View {
127127

128128
struct GroupOptionsListView: View {
129129

130-
var isSettleUpEnable: Bool
130+
@Binding var showShareSheet: Bool
131+
@Binding var showExportOptions: Bool
132+
133+
let isSettleUpEnable: Bool
131134

132135
let onSettleUpTap: () -> Void
133136
let onTransactionsTap: () -> Void
134137
let onBalanceTap: () -> Void
135138
let onTotalsTap: () -> Void
139+
let onExportTap: (ExportOptions, @escaping (Bool) -> Void) -> Void
136140

137141
var body: some View {
138142
ScrollView(.horizontal, showsIndicators: false) {
@@ -144,10 +148,51 @@ struct GroupOptionsListView: View {
144148
GroupOptionsButtonView(text: "Balances", onTap: onBalanceTap)
145149

146150
GroupOptionsButtonView(text: "Totals", onTap: onTotalsTap)
151+
152+
GroupOptionsButtonView(text: "Export") {
153+
showExportOptions = true
154+
}
147155
}
148156
.padding([.horizontal, .bottom], 16)
149157
.padding(.top, 24)
150158
}
159+
.confirmationDialog("", isPresented: $showExportOptions, titleVisibility: .hidden) {
160+
ForEach(ExportOptions.allCases, id: \.self) { option in
161+
Button(option.option.localized) {
162+
showExportOptions = false
163+
onExportTap(option) { _ in
164+
showShareSheet = true
165+
}
166+
}
167+
}
168+
}
169+
.sheet(isPresented: $showShareSheet) {
170+
ShareSheetView(activityItems: [""]) { isCompleted in
171+
if isCompleted {
172+
showShareSheet = false
173+
}
174+
}
175+
}
176+
}
177+
}
178+
179+
enum ExportOptions: Int, CaseIterable {
180+
181+
case month, threeMonths, sixMonths, year, all
182+
183+
var option: String {
184+
switch self {
185+
case .month:
186+
return "Month"
187+
case .threeMonths:
188+
return "Three months"
189+
case .sixMonths:
190+
return "Six months"
191+
case .year:
192+
return "Year"
193+
case .all:
194+
return "All"
195+
}
151196
}
152197
}
153198

‎Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject {
1717
@Inject var preference: SplitoPreference
1818
@Inject var groupRepository: GroupRepository
1919
@Inject var expenseRepository: ExpenseRepository
20-
@Inject private var transactionRepository: TransactionRepository
20+
@Inject var transactionRepository: TransactionRepository
2121

2222
@Published private(set) var groupId: String
2323
@Published private(set) var overallOwingAmount: Double = 0.0
@@ -32,8 +32,10 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject {
3232
@Published private(set) var memberOwingAmount: [String: Double] = [:]
3333
@Published private(set) var groupExpenses: [String: [ExpenseWithUser]] = [:]
3434

35+
@Published var showShareSheet = false
3536
@Published var showSettleUpSheet = false
3637
@Published var showBalancesSheet = false
38+
@Published var showExportOptions = false
3739
@Published var showGroupTotalSheet = false
3840
@Published var showAddExpenseSheet = false
3941
@Published var showTransactionsSheet = false

‎Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift

+33
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,39 @@ extension GroupHomeViewModel {
6060
onSearchBarCancelBtnTap()
6161
}
6262

63+
func handleExportTap(exportOption: ExportOptions, completion: @escaping (Bool) -> Void) {
64+
let calendar = Calendar.current
65+
let today = Date()
66+
var startDate: Date?
67+
68+
switch exportOption {
69+
case .month:
70+
startDate = calendar.date(byAdding: .month, value: -1, to: today) ?? today
71+
case .threeMonths:
72+
startDate = calendar.date(byAdding: .month, value: -3, to: today) ?? today
73+
case .sixMonths:
74+
startDate = calendar.date(byAdding: .month, value: -6, to: today) ?? today
75+
case .year:
76+
startDate = calendar.date(byAdding: .year, value: -1, to: today) ?? today
77+
case .all:
78+
startDate = nil
79+
}
80+
81+
Task {
82+
do {
83+
let expenses = try await expenseRepository.fetchExpenses(groupId: groupId, startDate: startDate, endDate: today)
84+
let transactions = try await transactionRepository.fetchTransactions(groupId: groupId, startDate: startDate, endDate: today)
85+
print("xxx \(expenses.count) \(transactions.count)")
86+
LogD("GroupHomeViewModel: \(#function) Expenses/payments fetched successfully.")
87+
completion(true)
88+
} catch {
89+
LogE("GroupHomeViewModel: \(#function) Failed to fetch Expenses/payments: \(error).")
90+
showToastForError()
91+
completion(false)
92+
}
93+
}
94+
}
95+
6396
func handleSimplifyInfoSheet() {
6497
UIApplication.shared.endEditing()
6598
showSimplifyInfoSheet = true

0 commit comments

Comments
 (0)
Please sign in to comment.