Skip to content

Commit

Permalink
Merge pull request #6 from VGVentures/feat/use-financial-bloc-data
Browse files Browse the repository at this point in the history
refactor: use financial bloc data instead of hardcoded
  • Loading branch information
jsgalarraga authored Aug 5, 2024
2 parents f22a6b0 + 15f9514 commit f4386d9
Show file tree
Hide file tree
Showing 21 changed files with 216 additions and 196 deletions.
5 changes: 4 additions & 1 deletion lib/demo/view/demo_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ class DemoPage extends StatelessWidget {
providers: [
BlocProvider(create: (_) => ThemeModeCubit()),
BlocProvider(create: (_) => FlavorCubit()),
BlocProvider(create: (_) => FinancialDataBloc()),
BlocProvider(
create: (_) =>
FinancialDataBloc()..add(const FinancialDataRequested()),
),
],
child: const DemoView(),
);
Expand Down
7 changes: 2 additions & 5 deletions lib/demo/widgets/app_one.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import 'package:flutter/material.dart';
class AppOne extends StatelessWidget {
const AppOne({super.key});

static final _currentSavings = ValueNotifier<String?>(null);

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Expand All @@ -23,10 +21,9 @@ class AppOne extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CurrentSavings(savings: _currentSavings),
const CurrentSavings(),
const SizedBox(height: AppSpacing.md),
RetirementPredictionChart(
onCurrentSavings: (value) => _currentSavings.value = value,
showAnnotations: true,
),
],
Expand All @@ -46,7 +43,7 @@ class AppOne extends StatelessWidget {
),
const SizedBox(width: AppSpacing.xlg),
const Expanded(
child: MonthlyGoal(amount: r'$3,125.00'),
child: MonthlyGoal(),
),
],
),
Expand Down
7 changes: 2 additions & 5 deletions lib/demo/widgets/app_three.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import 'package:flutter/material.dart';
class AppThree extends StatelessWidget {
const AppThree({super.key});

static final _currentSavings = ValueNotifier<String?>(null);

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Expand All @@ -24,12 +22,11 @@ class AppThree extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CurrentSavings(savings: _currentSavings),
const CurrentSavings(),
const SizedBox(height: AppSpacing.md),
RetirementPredictionChart(
showAreaElement: true,
selectedPointRadius: AppSpacing.xs,
onCurrentSavings: (value) => _currentSavings.value = value,
),
],
),
Expand All @@ -48,7 +45,7 @@ class AppThree extends StatelessWidget {
),
const SizedBox(width: AppSpacing.xlg),
const Expanded(
child: MonthlyGoal(amount: r'$1,125.00'),
child: MonthlyGoal(),
),
],
),
Expand Down
8 changes: 2 additions & 6 deletions lib/demo/widgets/app_two.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import 'package:flutter/material.dart';
class AppTwo extends StatelessWidget {
const AppTwo({super.key});

static final _currentSavings = ValueNotifier<String?>(null);

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Expand All @@ -30,9 +28,7 @@ class AppTwo extends StatelessWidget {
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.xlg,
),
child: RetirementPredictionChart(
onCurrentSavings: (value) => _currentSavings.value = value,
),
child: RetirementPredictionChart(),
),
Container(
height: spacing,
Expand Down Expand Up @@ -62,7 +58,7 @@ class AppTwo extends StatelessWidget {
horizontal: AppSpacing.md,
vertical: AppSpacing.lg,
),
child: CurrentSavings(savings: _currentSavings),
child: const CurrentSavings(),
),
),
),
Expand Down
20 changes: 8 additions & 12 deletions lib/demo/widgets/current_savings.dart
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
import 'package:financial_dashboard/financial_data/financial_data.dart';
import 'package:financial_dashboard/l10n/l10n.dart';
import 'package:financial_dashboard/ui/ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CurrentSavings extends StatelessWidget {
const CurrentSavings({
required this.savings,
super.key,
});

final ValueListenable<String?> savings;

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final textTheme = Theme.of(context).textTheme;
final currentSavings = context.select(
(FinancialDataBloc bloc) => bloc.state.currentSavings,
);

return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ValueListenableBuilder(
valueListenable: savings,
builder: (context, value, child) {
return Text(
'\$${value ?? ''}',
style: textTheme.displayMedium,
);
},
Text(
currentSavings.toCurrencyWithoutDecimal(),
style: textTheme.displayMedium,
),
const SizedBox(height: AppSpacing.xs),
Text(
Expand Down
12 changes: 7 additions & 5 deletions lib/demo/widgets/monthly_goal.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import 'package:financial_dashboard/financial_data/financial_data.dart';
import 'package:financial_dashboard/l10n/l10n.dart';
import 'package:financial_dashboard/ui/ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class MonthlyGoal extends StatelessWidget {
const MonthlyGoal({
required this.amount,
super.key,
});

final String amount;

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final theme = Theme.of(context);
final textTheme = theme.textTheme;
final colorScheme = theme.colorScheme;
final monthlySpendingLimitGoal = context.select(
(FinancialDataBloc bloc) => bloc.state.monthlySpendingLimitGoal,
);

return Card(
elevation: 0,
Expand All @@ -32,12 +34,12 @@ class MonthlyGoal extends StatelessWidget {
fit: BoxFit.scaleDown,
child: DefaultTextStyle(
style: textTheme.displaySmall!,
child: Text(amount),
child: Text(monthlySpendingLimitGoal.toCurrencyWithDecimals()),
),
),
const SizedBox(height: AppSpacing.xxs),
Text(
l10n.monthlyGoalLabel,
l10n.monthlySpendingLimitGoal,
style: textTheme.labelMedium,
),
],
Expand Down
49 changes: 9 additions & 40 deletions lib/demo/widgets/transactions_table.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,8 @@
import 'package:equatable/equatable.dart';
import 'package:financial_dashboard/financial_data/financial_data.dart';
import 'package:financial_dashboard/l10n/l10n.dart';
import 'package:financial_dashboard/ui/ui.dart';
import 'package:flutter/material.dart';

enum TransactionType { income, spendings }

class Transaction extends Equatable {
const Transaction({
required this.type,
required this.title,
required this.amount,
});

final TransactionType type;
final String title;
final String amount;

@override
List<Object> get props => [type, title, amount];
}
import 'package:flutter_bloc/flutter_bloc.dart';

class TransactionsTable extends StatelessWidget {
const TransactionsTable({
Expand All @@ -28,30 +12,15 @@ class TransactionsTable extends StatelessWidget {

final TextStyle? titleStyle;

static const _transactions = <Transaction>[
Transaction(
type: TransactionType.income,
title: 'Paycheck',
amount: r'+$3,000',
),
Transaction(
type: TransactionType.spendings,
title: 'Rent',
amount: r'-$1,000',
),
Transaction(
type: TransactionType.spendings,
title: 'Food',
amount: r'-$800',
),
];

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final theme = Theme.of(context);
final textTheme = theme.textTheme;
final colorScheme = theme.colorScheme;
final transactions = context.select(
(FinancialDataBloc bloc) => bloc.state.transactions,
);

return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
Expand All @@ -65,20 +34,20 @@ class TransactionsTable extends StatelessWidget {
context: context,
color: colorScheme.surfaceContainerHighest,
tiles: [
for (final transaction in _transactions)
for (final transaction in transactions)
ListTile(
contentPadding: EdgeInsets.zero,
title: Text(transaction.title),
subtitle: DefaultTextStyle(
style: textTheme.bodyMedium!.copyWith(
color: colorScheme.onSurfaceVariant.withOpacity(0.8),
),
child: transaction.type == TransactionType.income
child: transaction.amount > 0
? Text(l10n.incomeTransactionLabel)
: Text(l10n.spendingsTransactionLabel),
: Text(l10n.expenseTransactionLabel),
),
trailing: Text(
transaction.amount,
transaction.amount.toCurrencyWithoutDecimal(),
style: textTheme.bodyLarge?.copyWith(
fontWeight: AppFontWeight.semiBold,
),
Expand Down
8 changes: 4 additions & 4 deletions lib/financial_data/bloc/financial_data_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ class FinancialDataBloc extends Bloc<FinancialDataEvent, FinancialDataState> {
state.copyWith(
currentSavings: 234567.91,
savingsDataPoints: createSampleData(),
monthlySpendingGoal: 3210.55,
monthlySpendingLimitGoal: 3210.55,
transactions: [
const Transaction(name: 'Paycheck', amount: 3000),
const Transaction(name: 'Rent', amount: 1050.20),
const Transaction(name: 'Food', amount: 670.50),
const Transaction(title: 'Paycheck', amount: 3000),
const Transaction(title: 'Rent', amount: -1050.20),
const Transaction(title: 'Food', amount: -670.50),
],
),
);
Expand Down
25 changes: 17 additions & 8 deletions lib/financial_data/bloc/financial_data_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ class FinancialDataState extends Equatable {
const FinancialDataState({
this.currentSavings = 0,
this.savingsDataPoints = const [],
this.monthlySpendingGoal = 0,
this.monthlySpendingLimitGoal = 0,
this.transactions = const [],
});

final double currentSavings;
final List<SavingsDataPoint> savingsDataPoints;
final double monthlySpendingGoal;
final double monthlySpendingLimitGoal;
final List<Transaction> transactions;

FinancialDataState copyWith({
double? currentSavings,
List<SavingsDataPoint>? savingsDataPoints,
double? monthlySpendingGoal,
double? monthlySpendingLimitGoal,
List<Transaction>? transactions,
}) {
return FinancialDataState(
currentSavings: currentSavings ?? this.currentSavings,
savingsDataPoints: savingsDataPoints ?? this.savingsDataPoints,
monthlySpendingGoal: monthlySpendingGoal ?? this.monthlySpendingGoal,
monthlySpendingLimitGoal:
monthlySpendingLimitGoal ?? this.monthlySpendingLimitGoal,
transactions: transactions ?? this.transactions,
);
}
Expand All @@ -31,7 +32,7 @@ class FinancialDataState extends Equatable {
List<Object> get props => [
currentSavings,
savingsDataPoints,
monthlySpendingGoal,
monthlySpendingLimitGoal,
transactions,
];
}
Expand All @@ -51,13 +52,21 @@ class SavingsDataPoint extends Equatable {

class Transaction extends Equatable {
const Transaction({
required this.name,
required this.title,
required this.amount,
});

final String name;
final String title;
final double amount;

@override
List<Object?> get props => [name, amount];
List<Object?> get props => [title, amount];
}

extension TransactionListX on List<Transaction> {
List<Transaction> get expenses =>
where((element) => element.amount < 0).toList();

double get spent =>
expenses.fold(0, (value, element) => value + element.amount);
}
4 changes: 2 additions & 2 deletions lib/financial_data/extensions/financial_formatter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:intl/intl.dart';

extension FinancialFormatterX on double {
String toCurrencyWithoutDecimal() =>
'\$${NumberFormat('###,###').format(this)}';
NumberFormat.currency(decimalDigits: 0, symbol: r'$').format(this);

String toCurrencyWithDecimals() =>
'\$${NumberFormat('###,###.00').format(this)}';
NumberFormat.currency(decimalDigits: 2, symbol: r'$').format(this);
}
Loading

0 comments on commit f4386d9

Please sign in to comment.