Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement export group report support #99

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion Data/Data/Repository/CommentRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public class CommentRepository {
let payerName = (user.id == transaction.payerId && memberId == transaction.payerId) ?
(user.id == transaction.addedBy ? "You" : "you") :
(memberId == transaction.payerId) ? "you" : members.payer.nameWithLastInitial

cp-nirali-s marked this conversation as resolved.
Show resolved Hide resolved
let receiverName = (memberId == transaction.receiverId) ? "you" : (memberId == transaction.receiverId) ? "you" : members.receiver.nameWithLastInitial

context = ActivityLogContext(group: group, transaction: transaction, comment: comment,
Expand Down
4 changes: 4 additions & 0 deletions Data/Data/Repository/ExpenseRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ public class ExpenseRepository: ObservableObject {
return try await store.fetchExpensesBy(groupId: groupId, limit: limit, lastDocument: lastDocument)
}

public func fetchExpenses(groupId: String, startDate: Date?, endDate: Date) async throws -> [Expense] {
try await store.fetchExpenses(groupId: groupId, startDate: startDate, endDate: endDate)
}

public func fetchExpenseBy(groupId: String, expenseId: String) async throws -> Expense {
return try await store.fetchExpenseBy(groupId: groupId, expenseId: expenseId)
}
Expand Down
4 changes: 4 additions & 0 deletions Data/Data/Repository/TransactionRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ public class TransactionRepository: ObservableObject {
try await store.fetchTransactionsBy(groupId: groupId, limit: limit, lastDocument: lastDocument)
}

public func fetchTransactions(groupId: String, startDate: Date?, endDate: Date) async throws -> [Transactions] {
try await store.fetchTransactions(groupId: groupId, startDate: startDate, endDate: endDate)
}

public func fetchTransactionBy(groupId: String, transactionId: String) async throws -> Transactions {
try await store.fetchTransactionsBy(groupId: groupId, transactionId: transactionId)
}
Expand Down
23 changes: 23 additions & 0 deletions Data/Data/Store/ExpenseStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@ public class ExpenseStore: ObservableObject {
return (expenses, snapshot.documents.last)
}

func fetchExpenses(groupId: String, startDate: Date?, endDate: Date) async throws -> [Expense] {
if let startDate {
let startTimestamp = Timestamp(date: startDate)
let endTimestamp = Timestamp(date: endDate)

let query = expenseReference(groupId: groupId)
.whereField("is_active", isEqualTo: true)
.whereField("date", isGreaterThanOrEqualTo: startTimestamp)
.whereField("date", isLessThanOrEqualTo: endTimestamp)

let snapshot = try await query.getDocuments(source: .server).documents

return try snapshot.map { document in
try document.data(as: Expense.self)
}
} else {
return try await expenseReference(groupId: groupId)
.whereField("is_active", isEqualTo: true)
.order(by: "date", descending: true)
.getDocuments(as: Expense.self).data
}
}

func fetchExpensesOfAllGroups(userId: String, activeGroupIds: [String], limit: Int,
lastDocument: DocumentSnapshot?) async throws -> (expenses: [Expense], lastDocument: DocumentSnapshot?) {

Expand Down
23 changes: 23 additions & 0 deletions Data/Data/Store/TransactionStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,29 @@ public class TransactionStore: ObservableObject {
return (transactions, snapshot.documents.last)
}

func fetchTransactions(groupId: String, startDate: Date?, endDate: Date) async throws -> [Transactions] {
if let startDate {
let startTimestamp = Timestamp(date: startDate)
let endTimestamp = Timestamp(date: endDate)

let query = transactionReference(groupId: groupId)
.whereField("is_active", isEqualTo: true)
.whereField("date", isGreaterThanOrEqualTo: startTimestamp)
.whereField("date", isLessThanOrEqualTo: endTimestamp)

let snapshot = try await query.getDocuments(source: .server).documents

return try snapshot.map { document in
try document.data(as: Transactions.self)
}
} else {
return try await transactionReference(groupId: groupId)
.whereField("is_active", isEqualTo: true)
.order(by: "date", descending: true)
.getDocuments(as: Transactions.self).data
}
}
cp-nirali-s marked this conversation as resolved.
Show resolved Hide resolved

func fetchTransactionsBy(groupId: String, transactionId: String) async throws -> Transactions {
try await transactionReference(groupId: groupId)
.document(transactionId)
Expand Down
8 changes: 6 additions & 2 deletions Splito/UI/Home/Groups/Group/GroupExpenseListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ struct GroupExpenseListView: View {
GeometryReader { geometry in
ScrollViewReader { scrollProxy in
VStack(alignment: .leading, spacing: 0) {
GroupOptionsListView(isSettleUpEnable: (!viewModel.memberOwingAmount.isEmpty && viewModel.group?.members.count ?? 1 > 1),
GroupOptionsListView(showShareSheet: $viewModel.showShareSheet, showExportOptions: $viewModel.showExportOptions,
isSettleUpEnable: (!viewModel.memberOwingAmount.isEmpty && viewModel.group?.members.count ?? 1 > 1),
onSettleUpTap: viewModel.handleSettleUpBtnTap,
onTransactionsTap: viewModel.handleTransactionsBtnTap,
onBalanceTap: viewModel.handleBalancesBtnTap,
onTotalsTap: viewModel.handleTotalBtnTap)
onTotalsTap: viewModel.handleTotalBtnTap,
onExportTap: { exportOption, completion in
viewModel.handleExportTap(exportOption: exportOption, completion: completion)
})

if viewModel.showSearchBar {
SearchBar(text: $viewModel.searchedExpense, isFocused: isFocused, placeholder: "Search expenses")
Expand Down
47 changes: 46 additions & 1 deletion Splito/UI/Home/Groups/Group/GroupHomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,16 @@ struct GroupHomeView: View {

struct GroupOptionsListView: View {

var isSettleUpEnable: Bool
@Binding var showShareSheet: Bool
@Binding var showExportOptions: Bool

let isSettleUpEnable: Bool

let onSettleUpTap: () -> Void
let onTransactionsTap: () -> Void
let onBalanceTap: () -> Void
let onTotalsTap: () -> Void
let onExportTap: (ExportOptions, @escaping (Bool) -> Void) -> Void

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

GroupOptionsButtonView(text: "Totals", onTap: onTotalsTap)

GroupOptionsButtonView(text: "Export") {
showExportOptions = true
}
}
.padding([.horizontal, .bottom], 16)
.padding(.top, 24)
}
.confirmationDialog("", isPresented: $showExportOptions, titleVisibility: .hidden) {
ForEach(ExportOptions.allCases, id: \.self) { option in
Button(option.option.localized) {
showExportOptions = false
onExportTap(option) { _ in
showShareSheet = true
}
}
}
}
.sheet(isPresented: $showShareSheet) {
ShareSheetView(activityItems: [""]) { isCompleted in
if isCompleted {
showShareSheet = false
}
}
}
}
}

enum ExportOptions: Int, CaseIterable {

case month, threeMonths, sixMonths, year, all

var option: String {
switch self {
case .month:
return "Month"
case .threeMonths:
return "Three months"
case .sixMonths:
return "Six months"
case .year:
return "Year"
case .all:
return "All"
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject {
@Inject var preference: SplitoPreference
@Inject var groupRepository: GroupRepository
@Inject var expenseRepository: ExpenseRepository
@Inject private var transactionRepository: TransactionRepository
@Inject var transactionRepository: TransactionRepository
cp-nirali-s marked this conversation as resolved.
Show resolved Hide resolved

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

@Published var showShareSheet = false
@Published var showSettleUpSheet = false
@Published var showBalancesSheet = false
@Published var showExportOptions = false
@Published var showGroupTotalSheet = false
@Published var showAddExpenseSheet = false
@Published var showTransactionsSheet = false
Expand Down
33 changes: 33 additions & 0 deletions Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@ extension GroupHomeViewModel {
onSearchBarCancelBtnTap()
}

func handleExportTap(exportOption: ExportOptions, completion: @escaping (Bool) -> Void) {
let calendar = Calendar.current
let today = Date()
var startDate: Date?

switch exportOption {
case .month:
startDate = calendar.date(byAdding: .month, value: -1, to: today) ?? today
case .threeMonths:
startDate = calendar.date(byAdding: .month, value: -3, to: today) ?? today
case .sixMonths:
startDate = calendar.date(byAdding: .month, value: -6, to: today) ?? today
case .year:
startDate = calendar.date(byAdding: .year, value: -1, to: today) ?? today
case .all:
startDate = nil
}

Task {
do {
let expenses = try await expenseRepository.fetchExpenses(groupId: groupId, startDate: startDate, endDate: today)
let transactions = try await transactionRepository.fetchTransactions(groupId: groupId, startDate: startDate, endDate: today)
print("xxx \(expenses.count) \(transactions.count)")
LogD("GroupHomeViewModel: \(#function) Expenses/payments fetched successfully.")
completion(true)
} catch {
LogE("GroupHomeViewModel: \(#function) Failed to fetch Expenses/payments: \(error).")
showToastForError()
completion(false)
}
}
cp-nirali-s marked this conversation as resolved.
Show resolved Hide resolved
}

func handleSimplifyInfoSheet() {
UIApplication.shared.endEditing()
showSimplifyInfoSheet = true
Expand Down
Loading