-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from VGVentures/feat/add-financial-bloc
feat: add financial bloc
- Loading branch information
Showing
12 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import 'package:bloc/bloc.dart'; | ||
import 'package:equatable/equatable.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
|
||
part 'financial_data_event.dart'; | ||
part 'financial_data_state.dart'; | ||
|
||
class FinancialDataBloc extends Bloc<FinancialDataEvent, FinancialDataState> { | ||
FinancialDataBloc() : super(const FinancialDataState()) { | ||
on<FinancialDataRequested>(_onLoadFinancialData); | ||
} | ||
|
||
Future<void> _onLoadFinancialData( | ||
FinancialDataRequested event, | ||
Emitter<FinancialDataState> emit, | ||
) async { | ||
emit( | ||
state.copyWith( | ||
currentSavings: 234567.91, | ||
savingsDataPoints: createSampleData(), | ||
monthlySpendingGoal: 3210.55, | ||
transactions: [ | ||
const Transaction(name: 'Paycheck', amount: 3000), | ||
const Transaction(name: 'Rent', amount: 1050.20), | ||
const Transaction(name: 'Food', amount: 670.50), | ||
], | ||
), | ||
); | ||
} | ||
} | ||
|
||
@visibleForTesting | ||
List<SavingsDataPoint> createSampleData() { | ||
final data = <SavingsDataPoint>[]; | ||
var value = 100000.0; | ||
for (var age = 25; age <= 90; age++) { | ||
const toAdd = 10000; | ||
value += toAdd; | ||
data.add( | ||
SavingsDataPoint(age: age, value: value), | ||
); | ||
} | ||
return data; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
part of 'financial_data_bloc.dart'; | ||
|
||
sealed class FinancialDataEvent extends Equatable { | ||
const FinancialDataEvent(); | ||
|
||
@override | ||
List<Object> get props => []; | ||
} | ||
|
||
class FinancialDataRequested extends FinancialDataEvent { | ||
const FinancialDataRequested(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
part of 'financial_data_bloc.dart'; | ||
|
||
class FinancialDataState extends Equatable { | ||
const FinancialDataState({ | ||
this.currentSavings = 0, | ||
this.savingsDataPoints = const [], | ||
this.monthlySpendingGoal = 0, | ||
this.transactions = const [], | ||
}); | ||
|
||
final double currentSavings; | ||
final List<SavingsDataPoint> savingsDataPoints; | ||
final double monthlySpendingGoal; | ||
final List<Transaction> transactions; | ||
|
||
FinancialDataState copyWith({ | ||
double? currentSavings, | ||
List<SavingsDataPoint>? savingsDataPoints, | ||
double? monthlySpendingGoal, | ||
List<Transaction>? transactions, | ||
}) { | ||
return FinancialDataState( | ||
currentSavings: currentSavings ?? this.currentSavings, | ||
savingsDataPoints: savingsDataPoints ?? this.savingsDataPoints, | ||
monthlySpendingGoal: monthlySpendingGoal ?? this.monthlySpendingGoal, | ||
transactions: transactions ?? this.transactions, | ||
); | ||
} | ||
|
||
@override | ||
List<Object> get props => [ | ||
currentSavings, | ||
savingsDataPoints, | ||
monthlySpendingGoal, | ||
transactions, | ||
]; | ||
} | ||
|
||
class SavingsDataPoint extends Equatable { | ||
const SavingsDataPoint({ | ||
required this.age, | ||
required this.value, | ||
}); | ||
|
||
final int age; | ||
final double value; | ||
|
||
@override | ||
List<Object?> get props => [age, value]; | ||
} | ||
|
||
class Transaction extends Equatable { | ||
const Transaction({ | ||
required this.name, | ||
required this.amount, | ||
}); | ||
|
||
final String name; | ||
final double amount; | ||
|
||
@override | ||
List<Object?> get props => [name, amount]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export 'financial_formatter.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import 'package:intl/intl.dart'; | ||
|
||
extension FinancialFormatterX on double { | ||
String toCurrencyWithoutDecimal() => | ||
'\$${NumberFormat('###,###').format(this)}'; | ||
|
||
String toCurrencyWithDecimals() => | ||
'\$${NumberFormat('###,###.00').format(this)}'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export 'bloc/financial_data_bloc.dart'; | ||
export 'extensions/extensions.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
include: package:very_good_analysis/analysis_options.6.0.0.yaml | ||
linter: | ||
rules: | ||
public_member_api_docs: false | ||
prefer_const_constructors: false | ||
prefer_const_literals_to_create_immutables: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import 'package:bloc_test/bloc_test.dart'; | ||
import 'package:financial_dashboard/financial_data/financial_data.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
group('FinancialDataBloc', () { | ||
blocTest<FinancialDataBloc, FinancialDataState>( | ||
'loads financial data when $FinancialDataRequested is added', | ||
build: FinancialDataBloc.new, | ||
act: (bloc) => bloc.add(FinancialDataRequested()), | ||
expect: () => [ | ||
FinancialDataState( | ||
currentSavings: 234567.91, | ||
savingsDataPoints: createSampleData(), | ||
monthlySpendingGoal: 3210.55, | ||
transactions: [ | ||
const Transaction(name: 'Paycheck', amount: 3000), | ||
const Transaction(name: 'Rent', amount: 1050.20), | ||
const Transaction(name: 'Food', amount: 670.50), | ||
], | ||
), | ||
], | ||
); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import 'package:financial_dashboard/financial_data/financial_data.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
group('FinancialDataRequested', () { | ||
test('supports value equality', () { | ||
final eventA = FinancialDataRequested(); | ||
final eventB = FinancialDataRequested(); | ||
|
||
expect(eventA, equals(eventB)); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import 'package:financial_dashboard/financial_data/financial_data.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
group('FinancialDataState', () { | ||
test('supports value equality', () { | ||
expect(FinancialDataState(), equals(FinancialDataState())); | ||
}); | ||
|
||
group('copyWith', () { | ||
test('copies currentSavings', () { | ||
final state = FinancialDataState(); | ||
final newState = state.copyWith(currentSavings: 123.45); | ||
|
||
expect(newState.currentSavings, 123.45); | ||
}); | ||
|
||
test('copies savingsDataPoints', () { | ||
final state = FinancialDataState(); | ||
final dataPoint = SavingsDataPoint(age: 25, value: 100); | ||
final newState = state.copyWith(savingsDataPoints: [dataPoint]); | ||
|
||
expect(newState.savingsDataPoints, equals([dataPoint])); | ||
}); | ||
|
||
test('copies monthlySpendingGoal', () { | ||
final state = FinancialDataState(); | ||
final newState = state.copyWith(monthlySpendingGoal: 123.45); | ||
|
||
expect(newState.monthlySpendingGoal, 123.45); | ||
}); | ||
|
||
test('copies transactions', () { | ||
final state = FinancialDataState(); | ||
final transaction = Transaction(name: 'test', amount: 123.45); | ||
final newState = state.copyWith(transactions: [transaction]); | ||
|
||
expect(newState.transactions, equals([transaction])); | ||
}); | ||
}); | ||
}); | ||
|
||
group('SavingsDataPoint', () { | ||
test('supports value equality', () { | ||
const pointA = SavingsDataPoint(age: 25, value: 100); | ||
const secondPointA = SavingsDataPoint(age: 25, value: 100); | ||
const pointB = SavingsDataPoint(age: 52, value: 200); | ||
|
||
expect(pointA, equals(secondPointA)); | ||
expect(pointA, isNot(equals(pointB))); | ||
}); | ||
}); | ||
|
||
group('Transaction', () { | ||
test('supports value equality', () { | ||
const pointA = Transaction(name: 'test', amount: 100); | ||
const secondPointA = Transaction(name: 'test', amount: 100); | ||
const pointB = Transaction(name: 'test-two', amount: 200); | ||
|
||
expect(pointA, equals(secondPointA)); | ||
expect(pointA, isNot(equals(pointB))); | ||
}); | ||
}); | ||
} |
20 changes: 20 additions & 0 deletions
20
test/financial_data/extensions/financial_formatter_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import 'package:financial_dashboard/financial_data/financial_data.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
group('FinancialFormatterX', () { | ||
test('converts double to currency without decimals', () { | ||
expect( | ||
123456.789.toCurrencyWithoutDecimal(), | ||
r'$123,457', | ||
); | ||
}); | ||
|
||
test('converts double to currency with decimals', () { | ||
expect( | ||
123456.789.toCurrencyWithDecimals(), | ||
r'$123,456.79', | ||
); | ||
}); | ||
}); | ||
} |