Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions mobile/lib/features/analytics/presentation/pages/analytics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';

import 'package:twoaxis_finance/features/user/presentation/bloc/user_cubit.dart';
import 'package:twoaxis_finance/features/user/presentation/bloc/user_state.dart';
import 'package:twoaxis_finance/features/transactions/presentation/bloc/transactions_bloc.dart';
import 'package:twoaxis_finance/features/transactions/domain/transaction_repository.dart';
import 'package:twoaxis_finance/features/transactions/domain/transaction_type.dart';
import 'package:twoaxis_finance/core/util/money_format.dart';

Expand Down Expand Up @@ -140,13 +140,24 @@ class AnalyticsPage extends StatelessWidget {
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25),
),
SizedBox(height: 30),
BlocBuilder<TransactionsBloc, TransactionsState>(
builder: (context, state) {
if (state is! TransactionsStateLoaded) {
FutureBuilder(
future: () {
var now = DateTime.now();
var start = DateTime(now.year, now.month, now.day).subtract(Duration(days: 6));
var end = DateTime(now.year, now.month, now.day, 23, 59, 59);
return context.read<TransactionRepository>().getTransactionsByDateRange(start, end);
}(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}

var spots = generateExpenseSpots(state.transactions);
if (snapshot.hasError) {
return Center(child: Text("Error loading chart data"));
}

var transactions = snapshot.data ?? [];
var spots = generateExpenseSpots(transactions);

return SizedBox(
height: 200,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,72 @@ class TransactionRepositoryImpl implements TransactionRepository {
}

@override
Future<List<Transaction>> getAllTransactions() async {
Future<Map<String, dynamic>> getTransactions({int limit = 30, Object? startAfter}) async {
try {
var uid = _auth.currentUser?.uid;
if (uid == null) {
developer.log("getAllTransactions: User ID is null");
return [];
developer.log("getTransactions: User ID is null");
return {'transactions': <Transaction>[], 'lastDocument': null};
}

var result = await _firestore
Query query = _firestore
.collection("users")
.doc(uid)
.collection("transactions")
.get();
.orderBy("date", descending: true)
.limit(limit);

if (startAfter != null && startAfter is DocumentSnapshot) {
query = query.startAfterDocument(startAfter);
}

var result = await query.get();

developer.log("getAllTransactions: Found ${result.docs.length} documents");
developer.log("getTransactions: Found ${result.docs.length} documents");

return result.docs.map((doc) {
List<Transaction> transactions = result.docs.map((doc) {
try {
return Transaction.fromFirestore(doc);
} catch (e) {
developer.log("Error parsing transaction ${doc.id}: $e");
rethrow;
}
}).toList();

DocumentSnapshot? lastDocument = result.docs.isNotEmpty ? result.docs.last : null;

return {
'transactions': transactions,
'lastDocument': lastDocument,
};
} catch (e) {
developer.log("Error in getTransactions: $e");
rethrow;
}
}

@override
Future<List<Transaction>> getTransactionsByDateRange(DateTime start, DateTime end) async {
try {
var uid = _auth.currentUser?.uid;
if (uid == null) {
return [];
}

var result = await _firestore
.collection("users")
.doc(uid)
.collection("transactions")
.where("date", isGreaterThanOrEqualTo: start)
.where("date", isLessThanOrEqualTo: end)
.orderBy("date", descending: true)
.get();

return result.docs.map((doc) {
return Transaction.fromFirestore(doc);
}).toList();
} catch (e) {
developer.log("Error in getAllTransactions: $e");
developer.log("Error in getTransactionsByDateRange: $e");
rethrow;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:twoaxis_finance/features/transactions/domain/transaction.dart';
import 'package:twoaxis_finance/features/transactions/domain/transaction_type.dart';

abstract class TransactionRepository {

Future<List<Transaction>> getAllTransactions();
Future<Map<String, dynamic>> getTransactions({int limit = 30, Object? startAfter});
Future<List<Transaction>> getTransactionsByDateRange(DateTime start, DateTime end);
Future<String> addTransaction(String name, TransactionType type, double amount, {String? source, String? category, DateTime? date});
Future<void> deleteTransaction(String id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class TransactionsBloc extends Bloc<TransactionsEvent, TransactionsState> {
: _transactionRepository = transactionRepository,
super(TransactionsStateInitial()) {
on<LoadTransactionsEvent>(_onLoadTransactions);
on<LoadMoreTransactionsEvent>(_onLoadMoreTransactions);
on<AddTransactionEvent>(_onAddTransaction);
on<DeleteTransactionEvent>(_onDeleteTransaction);
}
Expand All @@ -25,7 +26,9 @@ class TransactionsBloc extends Bloc<TransactionsEvent, TransactionsState> {
) async {
emit(TransactionsStateLoading());
try {
var transactions = await _transactionRepository.getAllTransactions();
var result = await _transactionRepository.getTransactions(limit: 30);
var transactions = result['transactions'] as List<Transaction>;
var lastDocument = result['lastDocument'];

// Sort latest to oldest
transactions.sort((a, b) => b.date.compareTo(a.date));
Expand All @@ -35,6 +38,8 @@ class TransactionsBloc extends Bloc<TransactionsEvent, TransactionsState> {
emit(TransactionsStateLoaded(
transactions: transactions,
groupedTransactions: _groupTransactions(transactions),
hasReachedMax: transactions.length < 30,
lastDocument: lastDocument,
));

} catch (e, stackTrace) {
Expand All @@ -43,6 +48,44 @@ class TransactionsBloc extends Bloc<TransactionsEvent, TransactionsState> {
}
}

Future<void> _onLoadMoreTransactions(
LoadMoreTransactionsEvent event,
Emitter<TransactionsState> emit,
) async {
var currentState = state;
if (currentState is TransactionsStateLoaded && !currentState.hasReachedMax) {
try {
var result = await _transactionRepository.getTransactions(
limit: 30,
startAfter: currentState.lastDocument,
);
var newTransactions = result['transactions'] as List<Transaction>;
var lastDocument = result['lastDocument'];

if (newTransactions.isEmpty) {
emit(TransactionsStateLoaded(
transactions: currentState.transactions,
groupedTransactions: currentState.groupedTransactions,
hasReachedMax: true,
lastDocument: currentState.lastDocument,
));
} else {
var allTransactions = List<Transaction>.from(currentState.transactions)..addAll(newTransactions);
allTransactions.sort((a, b) => b.date.compareTo(a.date));

emit(TransactionsStateLoaded(
transactions: allTransactions,
groupedTransactions: _groupTransactions(allTransactions),
hasReachedMax: newTransactions.length < 30,
lastDocument: lastDocument,
));
}
} catch (e, stackTrace) {
developer.log("Error loading more transactions", error: e, stackTrace: stackTrace);
}
}
}

Future<void> _onAddTransaction(
AddTransactionEvent event,
Emitter<TransactionsState> emit,
Expand Down Expand Up @@ -81,6 +124,8 @@ class TransactionsBloc extends Bloc<TransactionsEvent, TransactionsState> {
emit(TransactionsStateLoaded(
transactions: updatedTransactions,
groupedTransactions: _groupTransactions(updatedTransactions),
hasReachedMax: currentState.hasReachedMax,
lastDocument: currentState.lastDocument,
));
} else {
add(LoadTransactionsEvent());
Expand All @@ -107,6 +152,8 @@ class TransactionsBloc extends Bloc<TransactionsEvent, TransactionsState> {
emit(TransactionsStateLoaded(
transactions: updatedTransactions,
groupedTransactions: _groupTransactions(updatedTransactions),
hasReachedMax: currentState.hasReachedMax,
lastDocument: currentState.lastDocument,
));
} else {
add(LoadTransactionsEvent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ abstract class TransactionsEvent extends Equatable {

class LoadTransactionsEvent extends TransactionsEvent {}

class LoadMoreTransactionsEvent extends TransactionsEvent {}

class AddTransactionEvent extends TransactionsEvent {
final String name;
final TransactionType type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ class TransactionsStateLoading extends TransactionsState {}
class TransactionsStateLoaded extends TransactionsState {
final List<Transaction> transactions;
final Map<DateTime, List<Transaction>> groupedTransactions;
final bool hasReachedMax;
final Object? lastDocument;

const TransactionsStateLoaded({
required this.transactions,
required this.groupedTransactions,
this.hasReachedMax = false,
this.lastDocument,
});

@override
List<Object?> get props => [transactions, groupedTransactions];
List<Object?> get props => [transactions, groupedTransactions, hasReachedMax, lastDocument];
}

class TransactionsStateError extends TransactionsState {
Expand Down
Loading
Loading