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

refactor: use financial bloc data instead of hardcoded #6

Merged
merged 8 commits into from
Aug 5, 2024
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
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(),
jsgalarraga marked this conversation as resolved.
Show resolved Hide resolved
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),
jsgalarraga marked this conversation as resolved.
Show resolved Hide resolved
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