@marcos_feitoza/personal-finance-frontend-feature-investments 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # [1.1.0](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/compare/v1.0.1...v1.1.0) (2025-11-28)
2
+
3
+
4
+ ### Features
5
+
6
+ * add confirmation dialog for deletion operations ([2972ee1](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/2972ee1e7abf6bb1c183554867006ccd1a9a0909))
7
+ * update readme.me ([56c5303](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/56c5303681a6110d25d600b11047be38b52f0cad))
8
+
9
+ ## [1.0.1](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/compare/v1.0.0...v1.0.1) (2025-11-27)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * add crypto table update ([e2e0da7](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/e2e0da77e334dd4416d04770db50be9b91bb0c06))
15
+ * fix and update the tables of investments ([ff5a7b5](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/ff5a7b56d627ebf0ef128e03ff6ad6a57efda042))
16
+ * update rrsp sl table ([107b6dc](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/107b6dce59621e3563e589e00b21f2fbbb529921))
17
+
1
18
  # 1.0.0 (2025-11-22)
2
19
 
3
20
 
package/README.md CHANGED
@@ -1,39 +1,34 @@
1
- <!--
2
- This README describes the package. If you publish this package to pub.dev,
3
- this README's contents appear on the landing page for your package.
1
+ # Feature: Investimentos (Frontend Flutter)
4
2
 
5
- For information about how to write a good package README, see the guide for
6
- [writing package pages](https://dart.dev/tools/pub/writing-package-pages).
3
+ Este pacote contém a implementação das telas para visualização e gerenciamento de todas as contas de investimento na aplicação Personal Finance Frontend.
7
4
 
8
- For general information about developing packages, see the Dart guide for
9
- [creating packages](https://dart.dev/guides/libraries/create-packages)
10
- and the Flutter guide for
11
- [developing packages and plugins](https://flutter.dev/to/develop-packages).
12
- -->
5
+ ## Propósito
13
6
 
14
- TODO: Put a short description of the package here that helps potential users
15
- know whether this package might be useful for them.
7
+ O objetivo deste pacote é fornecer ao usuário uma interface completa para acompanhar a performance de seus investimentos, registrar novas transações (compra/venda, dividendos) e gerenciar suas contribuições RRSP.
16
8
 
17
- ## Features
9
+ ## Conteúdo Principal
18
10
 
19
- TODO: List what your package can do. Maybe include images, gifs, or videos.
11
+ - **`lib/screens/investment_account_screen.dart`**: Tela genérica para contas de investimento (ex: TFSA, Non-Registered, RRSP Wealthsimple), mostrando resumo e histórico de trades.
12
+ - **`lib/screens/crypto_account_screen.dart`**: Tela específica para contas de criptomoedas, mostrando resumo e histórico de trades de cripto.
13
+ - **`lib/screens/rrsp_sun_life_screen.dart`**: Tela específica para a conta RRSP Sun Life, focando em histórico de contribuições.
20
14
 
21
- ## Getting started
15
+ ---
22
16
 
23
- TODO: List prerequisites and provide or point to information on how to
24
- start using the package.
17
+ ## Como Usar (Instalação como Dependência)
25
18
 
26
- ## Usage
19
+ Este pacote é uma dependência local para a aplicação principal (`personal-finance-frontend`).
27
20
 
28
- TODO: Include short and useful examples for package users. Add longer examples
29
- to `/example` folder.
21
+ No `pubspec.yaml` da aplicação principal, adicione a seguinte linha em `dependencies`:
30
22
 
31
- ```dart
32
- const like = 'sample';
23
+ ```yaml
24
+ personal_finance_frontend_feature_investments:
25
+ path: ../personal-finance-frontend-feature-investments
33
26
  ```
34
27
 
35
- ## Additional information
28
+ ## Features
36
29
 
37
- TODO: Tell users more about the package: where to find more information, how to
38
- contribute to the package, how to file issues, what response they can expect
39
- from the package authors, and more.
30
+ - **Resumo do Portfólio (Sintético)**: Visão geral da performance dos ativos em cada conta de investimento, com métricas como "Book Cost", "Market Value", "Unrealized P/L", "Total Return" e percentuais de alocação.
31
+ - **Histórico de Trades (Analítico)**: Listagem detalhada de todas as operações de compra e venda por conta.
32
+ - **Registro de Dividendos**: Formulário para registrar dividendos recebidos.
33
+ - **Acompanhamento de Contribuições RRSP**: Histórico e resumo das contribuições para contas RRSP.
34
+ - **Exclusão Suave (Soft Delete)**: Funcionalidade para deletar trades e contribuições de forma segura, marcando-os como excluídos em vez de remover permanentemente.
@@ -173,6 +173,7 @@ class _CryptoAccountScreenState extends State<CryptoAccountScreen> {
173
173
  return {'summary': result, 'total_value': accountPortfolioBookCost};
174
174
  }
175
175
 
176
+
176
177
  @override
177
178
  Widget build(BuildContext context) {
178
179
  return Scaffold(
@@ -349,7 +350,7 @@ class _CryptoAccountScreenState extends State<CryptoAccountScreen> {
349
350
  ),
350
351
  ],
351
352
  );
352
- },
353
+ }
353
354
  );
354
355
 
355
356
  if (confirm == true) {
@@ -378,4 +379,4 @@ class _CryptoAccountScreenState extends State<CryptoAccountScreen> {
378
379
  }
379
380
  }
380
381
  }
381
- }
382
+ }
@@ -7,6 +7,7 @@ import 'package:personal_finance_frontend_core_ui/widgets/dividend_log_form.dart
7
7
  import 'package:personal_finance_frontend_core_ui/widgets/app_widgets.dart';
8
8
  import 'package:provider/provider.dart';
9
9
  import 'package:personal_finance_frontend_core_services/providers/auth_provider.dart';
10
+ import 'package:personal_finance_frontend_core_ui/utils/app_dialogs.dart';
10
11
 
11
12
  class InvestmentAccountScreen extends StatefulWidget {
12
13
  final String accountName;
@@ -141,7 +142,8 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
141
142
  if (livePrice != null) {
142
143
  newTotalValue += shares * livePrice;
143
144
  } else {
144
- newTotalValue += (position['total_cost'] as num?)?.toDouble() ?? 0.0;
145
+ // If live price is not available, use book cost as a fallback for market value
146
+ newTotalValue += (position['book_cost'] as num?)?.toDouble() ?? 0.0;
145
147
  }
146
148
  }
147
149
 
@@ -155,7 +157,7 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
155
157
  Map<String, dynamic> _calculatePortfolioSummary(
156
158
  List<Map<String, dynamic>> trades, List<Map<String, dynamic>> dividends) {
157
159
  Map<String, dynamic> summary = {};
158
- double accountPortfolioBookCost = 0;
160
+ double accountTotalBookCost = 0;
159
161
 
160
162
  Map<String, double> dividendSummary = {};
161
163
  if (widget.showDividends) {
@@ -186,7 +188,7 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
186
188
  'name': asset['name'] ?? symbol,
187
189
  'industry': asset['industry'] ?? 'N/A',
188
190
  'shares': 0.0,
189
- 'total_cost': 0.0,
191
+ 'book_cost': 0.0, // Renamed from total_cost for clarity
190
192
  'total_dividends': dividendSummary[symbol] ?? 0.0,
191
193
  'first_trade_date': tradeDate,
192
194
  'last_activity_date': tradeDate,
@@ -202,12 +204,12 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
202
204
 
203
205
  if (tradeType == 'buy') {
204
206
  summary[symbol]['shares'] += shares;
205
- summary[symbol]['total_cost'] += shares * price;
207
+ summary[symbol]['book_cost'] += shares * price;
206
208
  } else if (tradeType == 'sell') {
207
209
  double originalShares = summary[symbol]['shares'];
208
210
  if (originalShares > 0) {
209
- double avgPrice = summary[symbol]['total_cost'] / originalShares;
210
- summary[symbol]['total_cost'] -= shares * avgPrice;
211
+ double avgPrice = summary[symbol]['book_cost'] / originalShares;
212
+ summary[symbol]['book_cost'] -= shares * avgPrice;
211
213
  }
212
214
  summary[symbol]['shares'] -= shares;
213
215
  }
@@ -215,21 +217,40 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
215
217
 
216
218
  summary.removeWhere((key, value) => value['shares'] < 0.01);
217
219
 
218
- accountPortfolioBookCost =
219
- summary.values.fold(0.0, (sum, item) => sum + item['total_cost']);
220
+ accountTotalBookCost =
221
+ summary.values.fold(0.0, (sum, item) => sum + item['book_cost']);
220
222
 
221
223
  List<Map<String, dynamic>> result = [];
222
224
  summary.forEach((symbol, data) {
223
225
  double shares = data['shares'];
224
- double totalCost = data['total_cost'];
225
- data['avg_price'] = (shares > 0) ? totalCost / shares : 0.0;
226
- data['account_allocation'] = (accountPortfolioBookCost > 0)
227
- ? (totalCost / accountPortfolioBookCost) * 100
226
+ double bookCost = data['book_cost'];
227
+ double totalDividends = data['total_dividends'];
228
+
229
+ data['avg_price'] = (shares > 0) ? bookCost / shares : 0.0;
230
+ data['account_allocation_percent'] = (accountTotalBookCost > 0)
231
+ ? (bookCost / accountTotalBookCost) * 100
232
+ : 0.0;
233
+ data['portfolio_allocation_percent'] = (_totalPortfolioBookCost > 0)
234
+ ? (bookCost / _totalPortfolioBookCost) * 100
228
235
  : 0.0;
236
+
237
+ // Calculate Market Value, Unrealized P/L, Total Return
238
+ final livePrice = _livePrices[symbol];
239
+ double marketValue = livePrice != null ? shares * livePrice : bookCost; // Fallback to bookCost if no live price
240
+ double unrealizedPL = marketValue - bookCost;
241
+ double totalReturn = unrealizedPL + totalDividends;
242
+
243
+ data['market_value'] = marketValue;
244
+ data['unrealized_pl'] = unrealizedPL;
245
+ data['total_return'] = totalReturn;
246
+
247
+ data['percent_unrealized_pl'] = (bookCost > 0) ? (unrealizedPL / bookCost) * 100 : 0.0;
248
+ data['percent_total_return'] = (bookCost > 0) ? (totalReturn / bookCost) * 100 : 0.0;
249
+
229
250
  result.add(data);
230
251
  });
231
252
 
232
- return {'summary': result, 'total_value': accountPortfolioBookCost};
253
+ return {'summary': result, 'total_value': accountTotalBookCost};
233
254
  }
234
255
 
235
256
  @override
@@ -357,111 +378,60 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
357
378
  columnSpacing: 24.0,
358
379
  columns: [
359
380
  const DataColumn(label: Text('Symbol')),
360
- const DataColumn(label: Text('Age')),
361
- const DataColumn(label: Text('Purchased')),
362
381
  const DataColumn(label: Text('Shares')),
363
382
  const DataColumn(label: Text('Avg Price')),
364
- const DataColumn(label: Text('Live')),
365
- const DataColumn(label: Text('Purchased')),
366
- const DataColumn(label: Text('Allocation')),
367
- const DataColumn(label: Text('Stocks Allocation')),
368
- const DataColumn(label: Text('Return')),
369
- const DataColumn(label: Text('% Return')),
370
383
  const DataColumn(label: Text('Book Cost')),
384
+ const DataColumn(label: Text('Live Price')),
385
+ const DataColumn(label: Text('Market Value')),
386
+ const DataColumn(label: Text('Unrealized P/L')),
387
+ const DataColumn(label: Text('% P/L')),
371
388
  if (widget.showDividends) ...[
372
389
  const DataColumn(label: Text('Dividends')),
373
- const DataColumn(label: Text('Return + Div')),
374
- const DataColumn(label: Text('Book Cost + Div')),
375
- const DataColumn(label: Text('% Return Div')),
390
+ const DataColumn(label: Text('Total Return')),
391
+ const DataColumn(label: Text('% Total Return')),
376
392
  ],
393
+ const DataColumn(label: Text('Account %')),
394
+ const DataColumn(label: Text('Portfolio %')),
377
395
  ],
378
396
  rows: _portfolioSummary.map((position) {
379
397
  final symbol = position['symbol'] as String;
398
+ final shares = position['shares'] as double;
399
+ final avgPrice = position['avg_price'] as double;
400
+ final bookCost = position['book_cost'] as double;
380
401
  final livePrice = _livePrices[symbol];
381
- final shares = double.parse(position['shares'].toString());
382
- final avgPrice = double.parse(position['avg_price'].toString());
383
- final totalPurchased =
384
- double.parse(position['total_cost'].toString());
385
- final accountAllocation =
386
- (position['account_allocation'] as num?)?.toDouble() ?? 0.0;
387
- final stocksAllocation = (_totalPortfolioBookCost > 0)
388
- ? (totalPurchased / _totalPortfolioBookCost) * 100
389
- : 0.0;
390
- final totalDividends =
391
- (position['total_dividends'] as num?)?.toDouble() ?? 0.0;
392
- final firstActivity = position['first_trade_date'] as DateTime?;
393
- final positionAge = firstActivity != null
394
- ? DateTime.now().difference(firstActivity)
395
- : null;
396
-
397
- double? totalReturnValue,
398
- percentageReturn,
399
- bookCost,
400
- returnPlusDividend,
401
- bookCostPlusDividend,
402
- percentageReturnDividend;
403
-
404
- if (livePrice != null && shares > 0) {
405
- final currentMarketValue = livePrice * shares;
406
- totalReturnValue = currentMarketValue - totalPurchased;
407
- bookCost = currentMarketValue;
408
- if (totalPurchased > 0)
409
- percentageReturn = (totalReturnValue / totalPurchased) * 100;
410
- if (widget.showDividends) {
411
- returnPlusDividend = totalReturnValue + totalDividends;
412
- bookCostPlusDividend = bookCost + totalDividends;
413
- if (totalPurchased > 0)
414
- percentageReturnDividend =
415
- (returnPlusDividend / totalPurchased) * 100;
416
- }
417
- }
418
-
419
- final returnColor =
420
- (totalReturnValue ?? 0) >= 0 ? Colors.green : Colors.red;
421
- final returnWithDivColor =
422
- (returnPlusDividend ?? 0) >= 0 ? Colors.green : Colors.red;
402
+ final marketValue = position['market_value'] as double;
403
+ final unrealizedPL = position['unrealized_pl'] as double;
404
+ final percentUnrealizedPL = position['percent_unrealized_pl'] as double;
405
+ final totalDividends = position['total_dividends'] as double;
406
+ final totalReturn = position['total_return'] as double;
407
+ final percentTotalReturn = position['percent_total_return'] as double;
408
+ final accountAllocationPercent = position['account_allocation_percent'] as double;
409
+ final portfolioAllocationPercent = position['portfolio_allocation_percent'] as double;
410
+
411
+
412
+ final plColor =
413
+ (unrealizedPL ?? 0) >= 0 ? Colors.green : Colors.red;
414
+ final totalReturnColor =
415
+ (totalReturn ?? 0) >= 0 ? Colors.green : Colors.red;
423
416
 
424
417
  return DataRow(cells: [
425
418
  DataCell(Text(symbol)),
426
- DataCell(Text(
427
- positionAge != null ? _formatDuration(positionAge) : 'N/A')),
428
- DataCell(Text(position['last_activity_date'] != null
429
- ? DateFormat('yyyy-MM-dd')
430
- .format(position['last_activity_date'])
431
- : 'N/A')),
432
419
  DataCell(Text(shares.toStringAsFixed(4))),
433
420
  DataCell(Text(_formatCurrency(avgPrice))),
421
+ DataCell(Text(_formatCurrency(bookCost))),
434
422
  DataCell(livePrice != null
435
423
  ? Text(_formatCurrency(livePrice))
436
424
  : const Text('N/A')),
437
- DataCell(Text(_formatCurrency(totalPurchased))),
438
- DataCell(Text('${accountAllocation.toStringAsFixed(2)}%')),
439
- DataCell(Text('${stocksAllocation.toStringAsFixed(2)}%')),
440
- DataCell(totalReturnValue != null
441
- ? Text(_formatCurrency(totalReturnValue),
442
- style: TextStyle(color: returnColor))
443
- : const Text('N/A')),
444
- DataCell(percentageReturn != null
445
- ? Text('${percentageReturn.toStringAsFixed(2)}%',
446
- style: TextStyle(color: returnColor))
447
- : const Text('N/A')),
448
- DataCell(bookCost != null
449
- ? Text(_formatCurrency(bookCost))
450
- : const Text('N/A')),
425
+ DataCell(Text(_formatCurrency(marketValue))),
426
+ DataCell(Text(_formatCurrency(unrealizedPL), style: TextStyle(color: plColor))),
427
+ DataCell(Text('${percentUnrealizedPL.toStringAsFixed(2)}%', style: TextStyle(color: plColor))),
451
428
  if (widget.showDividends) ...[
452
429
  DataCell(Text(_formatCurrency(totalDividends))),
453
- DataCell(returnPlusDividend != null
454
- ? Text(_formatCurrency(returnPlusDividend),
455
- style: TextStyle(color: returnWithDivColor))
456
- : const Text('N/A')),
457
- DataCell(bookCostPlusDividend != null
458
- ? Text(_formatCurrency(bookCostPlusDividend))
459
- : const Text('N/A')),
460
- DataCell(percentageReturnDividend != null
461
- ? Text('${percentageReturnDividend.toStringAsFixed(2)}%',
462
- style: TextStyle(color: returnWithDivColor))
463
- : const Text('N/A')),
464
- ]
430
+ DataCell(Text(_formatCurrency(totalReturn), style: TextStyle(color: totalReturnColor))),
431
+ DataCell(Text('${percentTotalReturn.toStringAsFixed(2)}%', style: TextStyle(color: totalReturnColor))),
432
+ ],
433
+ DataCell(Text('${accountAllocationPercent.toStringAsFixed(2)}%')),
434
+ DataCell(Text('${portfolioAllocationPercent.toStringAsFixed(2)}%')),
465
435
  ]);
466
436
  }).toList(),
467
437
  ),
@@ -575,25 +545,7 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
575
545
  }
576
546
 
577
547
  Future<void> _confirmAndDeleteTrade(int tradeId) async {
578
- final bool? confirm = await showDialog<bool>(
579
- context: context,
580
- builder: (BuildContext context) {
581
- return AlertDialog(
582
- title: const Text('Confirm Deletion'),
583
- content: const Text('Are you sure you want to delete this trade? This action cannot be undone.'),
584
- actions: <Widget>[
585
- TextButton(
586
- onPressed: () => Navigator.of(context).pop(false),
587
- child: const Text('Cancel'),
588
- ),
589
- TextButton(
590
- onPressed: () => Navigator.of(context).pop(true),
591
- child: const Text('Delete'),
592
- ),
593
- ],
594
- );
595
- },
596
- );
548
+ final bool? confirm = await AppDialogs.showDeleteConfirmationDialog(context, 'this trade');
597
549
 
598
550
  if (confirm == true) {
599
551
  if (_token == null) {
@@ -621,4 +573,4 @@ class _InvestmentAccountScreenState extends State<InvestmentAccountScreen> {
621
573
  }
622
574
  }
623
575
  }
624
- }
576
+ }
@@ -59,8 +59,6 @@ class _RrspSunLifeScreenState extends State<RrspSunLifeScreen> {
59
59
  final sinteticoSummaryData =
60
60
  _calculateSinteticoSummary(contributions, totalPortfolioBookCost);
61
61
 
62
- print('[DEBUG] Sintetico Summary Data: $sinteticoSummaryData');
63
-
64
62
  if (!mounted) return;
65
63
  setState(() {
66
64
  _contributions = contributions;
@@ -85,40 +83,35 @@ class _RrspSunLifeScreenState extends State<RrspSunLifeScreen> {
85
83
 
86
84
  Map<String, dynamic> _calculateSinteticoSummary(
87
85
  List<Map<String, dynamic>> contributions, double totalPortfolioBookCost) {
88
- double totalRrsp = 0;
89
-
90
- double totalDpsp = 0;
91
-
92
- double totalReturn = 0;
86
+ double totalUserContribution = 0;
87
+ double totalCompanyContribution = 0;
88
+ double totalUnrealizedPL = 0;
93
89
 
94
90
  for (var c in contributions) {
95
- totalRrsp += double.parse(c['rrsp_amount'].toString());
96
-
97
- totalDpsp += double.parse(c['dpsp_amount'].toString());
98
-
99
- totalReturn += double.parse(c['return_amount']?.toString() ?? '0.0');
91
+ totalUserContribution += double.parse(c['rrsp_amount'].toString());
92
+ totalCompanyContribution += double.parse(c['dpsp_amount'].toString());
93
+ totalUnrealizedPL += double.parse(c['return_amount']?.toString() ?? '0.0');
100
94
  }
101
95
 
102
- final totalPurchased = totalRrsp + totalDpsp;
103
-
104
- final bookCost = totalPurchased + totalReturn;
96
+ final totalContributed = totalUserContribution + totalCompanyContribution;
97
+ final marketValue = totalContributed + totalUnrealizedPL;
105
98
 
106
99
  final summaryData = {
107
- 'rrsp_amount': totalRrsp,
108
- 'dpsp_amount': totalDpsp,
109
- 'total_purchased': totalPurchased,
110
- 'return_amount': totalReturn,
100
+ 'user_contribution': totalUserContribution,
101
+ 'company_contribution': totalCompanyContribution,
102
+ 'total_contributed': totalContributed,
103
+ 'unrealized_pl': totalUnrealizedPL,
111
104
  'percent_return':
112
- (totalPurchased > 0) ? (totalReturn / totalPurchased) * 100 : 0.0,
113
- 'book_cost': bookCost,
114
- 'portfolio_allocation': (totalPortfolioBookCost > 0)
115
- ? (bookCost / totalPortfolioBookCost) * 100
105
+ (totalContributed > 0) ? (totalUnrealizedPL / totalContributed) * 100 : 0.0,
106
+ 'market_value': marketValue,
107
+ 'portfolio_allocation_percent': (totalPortfolioBookCost > 0)
108
+ ? (marketValue / totalPortfolioBookCost) * 100
116
109
  : 0.0,
117
110
  };
118
111
 
119
112
  return {
120
113
  'summary': [summaryData],
121
- 'total_value': bookCost
114
+ 'total_value': marketValue
122
115
  };
123
116
  }
124
117
 
@@ -191,27 +184,33 @@ class _RrspSunLifeScreenState extends State<RrspSunLifeScreen> {
191
184
  }
192
185
 
193
186
  final summary = _sinteticoSummary.first;
187
+ final double unrealizedPL = summary['unrealized_pl'];
188
+ final plColor = (unrealizedPL >= 0) ? Colors.green : Colors.red;
189
+
194
190
 
195
191
  return DataTable(
196
192
  columns: const [
197
- DataColumn(label: Text('RRSP')),
198
- DataColumn(label: Text('DPSP')),
199
- DataColumn(label: Text('Total Purchased')),
200
- DataColumn(label: Text('Return')),
193
+ DataColumn(label: Text('User Contr.')),
194
+ DataColumn(label: Text('Company Contr.')),
195
+ DataColumn(label: Text('Total Contributed')),
196
+ DataColumn(label: Text('Unrealized P/L')),
201
197
  DataColumn(label: Text('% Return')),
202
- DataColumn(label: Text('Book Cost')),
198
+ DataColumn(label: Text('Market Value')),
199
+ DataColumn(label: Text('Portfolio %')),
203
200
  ],
204
201
  rows: [
205
202
  DataRow(
206
203
  cells: [
207
- DataCell(Text(_formatCurrency(summary['rrsp_amount'] as double))),
208
- DataCell(Text(_formatCurrency(summary['dpsp_amount'] as double))),
204
+ DataCell(Text(_formatCurrency(summary['user_contribution'] as double))),
205
+ DataCell(Text(_formatCurrency(summary['company_contribution'] as double))),
209
206
  DataCell(
210
- Text(_formatCurrency(summary['total_purchased'] as double))),
211
- DataCell(Text(_formatCurrency(summary['return_amount'] as double))),
207
+ Text(_formatCurrency(summary['total_contributed'] as double))),
208
+ DataCell(Text(_formatCurrency(unrealizedPL), style: TextStyle(color: plColor))),
209
+ DataCell(Text(
210
+ '${(summary['percent_return'] as double).toStringAsFixed(2)}%', style: TextStyle(color: plColor))),
211
+ DataCell(Text(_formatCurrency(summary['market_value'] as double))),
212
212
  DataCell(Text(
213
- '${(summary['percent_return'] as double).toStringAsFixed(2)}%')),
214
- DataCell(Text(_formatCurrency(summary['book_cost'] as double))),
213
+ '${(summary['portfolio_allocation_percent'] as double).toStringAsFixed(2)}%')),
215
214
  ],
216
215
  ),
217
216
  ],
@@ -231,30 +230,30 @@ class _RrspSunLifeScreenState extends State<RrspSunLifeScreen> {
231
230
  return DataTable(
232
231
  columns: const [
233
232
  DataColumn(label: Text('Date')),
234
- DataColumn(label: Text('RRSP')),
235
- DataColumn(label: Text('DPSP')),
236
- DataColumn(label: Text('Total Purchased')),
233
+ DataColumn(label: Text('User Contr.')),
234
+ DataColumn(label: Text('Company Contr.')),
235
+ DataColumn(label: Text('Total Contributed')),
237
236
  DataColumn(label: Text('Return')),
238
237
  DataColumn(label: Text('% Return')),
239
- DataColumn(label: Text('Book Cost')),
240
- DataColumn(label: Text('Stock Allocation')),
241
- DataColumn(label: Text('Actions')), // New column
238
+ DataColumn(label: Text('Cumulative Value')),
239
+ DataColumn(label: Text('Portfolio %')),
240
+ DataColumn(label: Text('Actions')),
242
241
  ],
243
242
  rows: _contributions.map((c) {
244
243
  final contributionId = c['id'] as int;
245
244
  final rrspAmount = double.parse(c['rrsp_amount'].toString());
246
245
  final dpspAmount = double.parse(c['dpsp_amount'].toString());
247
- final totalPurchased = rrspAmount + dpspAmount;
246
+ final totalContributed = rrspAmount + dpspAmount;
248
247
 
249
248
  final returnAmount =
250
249
  double.parse(c['return_amount']?.toString() ?? '0.0');
251
250
  final percentReturn =
252
- totalPurchased > 0 ? (returnAmount / totalPurchased) * 100 : 0.0;
251
+ totalContributed > 0 ? (returnAmount / totalContributed) * 100 : 0.0;
253
252
 
254
- final bookCost = totalPurchased + returnAmount;
253
+ final cumulativeValue = totalContributed + returnAmount;
255
254
 
256
- final stockAllocation = _totalPortfolioBookCost > 0
257
- ? (bookCost / _totalPortfolioBookCost) * 100
255
+ final portfolioAllocation = _totalPortfolioBookCost > 0
256
+ ? (cumulativeValue / _totalPortfolioBookCost) * 100
258
257
  : 0.0;
259
258
 
260
259
  String dateStr;
@@ -272,12 +271,12 @@ class _RrspSunLifeScreenState extends State<RrspSunLifeScreen> {
272
271
  DataCell(Text(dateStr)),
273
272
  DataCell(Text(_formatCurrency(rrspAmount))),
274
273
  DataCell(Text(_formatCurrency(dpspAmount))),
275
- DataCell(Text(_formatCurrency(totalPurchased))),
274
+ DataCell(Text(_formatCurrency(totalContributed))),
276
275
  DataCell(Text(_formatCurrency(returnAmount))),
277
276
  DataCell(Text('${percentReturn.toStringAsFixed(2)}%')),
278
- DataCell(Text(_formatCurrency(bookCost))),
279
- DataCell(Text('${stockAllocation.toStringAsFixed(2)}%')),
280
- DataCell( // New cell for the delete button
277
+ DataCell(Text(_formatCurrency(cumulativeValue))),
278
+ DataCell(Text('${portfolioAllocation.toStringAsFixed(2)}%')),
279
+ DataCell(
281
280
  IconButton(
282
281
  icon: const Icon(Icons.delete, color: Colors.red),
283
282
  onPressed: () => _confirmAndDeleteContribution(contributionId),
@@ -337,4 +336,4 @@ class _RrspSunLifeScreenState extends State<RrspSunLifeScreen> {
337
336
  }
338
337
  }
339
338
  }
340
- }
339
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marcos_feitoza/personal-finance-frontend-feature-investments",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },