@marcos_feitoza/personal-finance-frontend-feature-investments 1.2.0 → 1.2.2

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,17 @@
1
+ ## [1.2.2](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/compare/v1.2.1...v1.2.2) (2026-01-30)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Web responsivo (mobile/tablet/resize) ([f3aa7b2](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/f3aa7b2edd456ca2fe1d32ea3a7f8798dc053fe9))
7
+
8
+ ## [1.2.1](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/compare/v1.2.0...v1.2.1) (2026-01-29)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * update SnackBar ([a8f6587](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/commit/a8f6587eb10895eedd77eaa8bf9e15c5efa53463))
14
+
1
15
  # [1.2.0](https://github.com/MarcosOps/personal-finance-frontend-feature-investments/compare/v1.1.2...v1.2.0) (2025-12-06)
2
16
 
3
17
 
@@ -3,6 +3,8 @@ import 'package:intl/intl.dart';
3
3
  import 'package:provider/provider.dart';
4
4
  import 'package:personal_finance_frontend_core_services/providers/auth_provider.dart';
5
5
  import 'package:personal_finance_frontend_core_ui/utils/app_dialogs.dart';
6
+ import 'package:personal_finance_frontend_core_ui/utils/app_responsive.dart';
7
+ import 'package:personal_finance_frontend_core_ui/utils/app_snackbars.dart';
6
8
  import 'package:personal_finance_frontend_core_ui/widgets/crypto_trade_form.dart';
7
9
  import '../viewmodels/crypto_account_viewmodel.dart';
8
10
 
@@ -118,8 +120,7 @@ class CryptoAccountScreen extends StatelessWidget {
118
120
  );
119
121
  }
120
122
 
121
- return SingleChildScrollView(
122
- scrollDirection: Axis.horizontal,
123
+ return ResponsiveHorizontalScroll(
123
124
  child: DataTable(
124
125
  columnSpacing: 24.0,
125
126
  columns: const [
@@ -204,7 +205,8 @@ class CryptoAccountScreen extends StatelessWidget {
204
205
  }
205
206
  });
206
207
 
207
- return DataTable(
208
+ return ResponsiveHorizontalScroll(
209
+ child: DataTable(
208
210
  columns: const [
209
211
  DataColumn(label: Text('Date')),
210
212
  DataColumn(label: Text('Symbol')),
@@ -238,6 +240,7 @@ class CryptoAccountScreen extends StatelessWidget {
238
240
  ),
239
241
  ]);
240
242
  }).toList(),
243
+ ),
241
244
  );
242
245
  }
243
246
 
@@ -249,13 +252,11 @@ class CryptoAccountScreen extends StatelessWidget {
249
252
  if (confirm == true) {
250
253
  final success = await viewModel.deleteTrade(tradeId);
251
254
  if (ScaffoldMessenger.of(context).mounted) {
252
- ScaffoldMessenger.of(context).showSnackBar(
253
- SnackBar(
254
- content: Text(success
255
- ? 'Trade deleted successfully.'
256
- : 'Failed to delete trade.'),
257
- ),
258
- );
255
+ if (success) {
256
+ showSuccessSnackBar(context, 'Trade deleted successfully.');
257
+ } else {
258
+ showErrorSnackBar(context, 'Failed to delete trade.');
259
+ }
259
260
  }
260
261
  }
261
262
  }
@@ -3,6 +3,8 @@ import 'package:intl/intl.dart';
3
3
  import 'package:provider/provider.dart';
4
4
  import 'package:personal_finance_frontend_core_services/providers/auth_provider.dart';
5
5
  import 'package:personal_finance_frontend_core_ui/utils/app_dialogs.dart';
6
+ import 'package:personal_finance_frontend_core_ui/utils/app_snackbars.dart';
7
+ import 'package:personal_finance_frontend_core_ui/utils/app_responsive.dart';
6
8
  import 'package:personal_finance_frontend_core_ui/widgets/trade_form.dart';
7
9
  import 'package:personal_finance_frontend_core_ui/widgets/dividend_log_form.dart';
8
10
  import 'package:personal_finance_frontend_core_ui/widgets/app_widgets.dart';
@@ -182,8 +184,7 @@ class InvestmentAccountScreen extends StatelessWidget {
182
184
  );
183
185
  }
184
186
 
185
- return SingleChildScrollView(
186
- scrollDirection: Axis.horizontal,
187
+ return ResponsiveHorizontalScroll(
187
188
  child: DataTable(
188
189
  columnSpacing: 24.0,
189
190
  columns: [
@@ -263,48 +264,57 @@ class InvestmentAccountScreen extends StatelessWidget {
263
264
  );
264
265
  }
265
266
 
266
- return DataTable(
267
- columns: const [
268
- DataColumn(label: Text('Date')),
269
- DataColumn(label: Text('Trade Age')),
270
- DataColumn(label: Text('Symbol')),
271
- DataColumn(label: Text('Type')),
272
- DataColumn(label: Text('Shares')),
273
- DataColumn(label: Text('Price')),
274
- DataColumn(label: Text('Total')),
275
- DataColumn(label: Text('Actions')),
276
- ],
277
- rows: filteredHistory.map((item) {
278
- final isTrade = item['history_type'] == 'trade';
279
- final isDividend = item['history_type'] == 'dividend';
267
+ return ResponsiveHorizontalScroll(
268
+ child: DataTable(
269
+ columns: const [
270
+ DataColumn(label: Text('Date')),
271
+ DataColumn(label: Text('Trade Age')),
272
+ DataColumn(label: Text('Symbol')),
273
+ DataColumn(label: Text('Type')),
274
+ DataColumn(label: Text('Shares')),
275
+ DataColumn(label: Text('Price')),
276
+ DataColumn(label: Text('Total')),
277
+ DataColumn(label: Text('Actions')),
278
+ ],
279
+ rows: filteredHistory.map((item) {
280
+ final isTrade = item['history_type'] == 'trade';
281
+ // final isDividend = item['history_type'] == 'dividend'; // Reserved for future use.
280
282
 
281
- final tradeDate = DateTime.parse(item['date'] as String);
282
- final tradeAge = DateTime.now().difference(tradeDate);
283
- final symbol = item['symbol'] as String? ?? 'N/A';
284
- final type = item['type'] as String? ?? 'N/A';
285
- final int id = item['id'] as int;
283
+ final tradeDate = DateTime.parse(item['date'] as String);
284
+ final tradeAge = DateTime.now().difference(tradeDate);
285
+ final symbol = item['symbol'] as String? ?? 'N/A';
286
+ final type = item['type'] as String? ?? 'N/A';
287
+ final int id = item['id'] as int;
286
288
 
287
- final double shares = isTrade ? (double.tryParse(item['shares']?.toString() ?? '0.0') ?? 0.0) : 0.0;
288
- final double price = isTrade ? (double.tryParse(item['price']?.toString() ?? '0.0') ?? 0.0) : 0.0;
289
- final double total = isTrade ? (shares * price) : (double.tryParse(item['total']?.toString() ?? '0.0') ?? 0.0);
289
+ final double shares = isTrade
290
+ ? (double.tryParse(item['shares']?.toString() ?? '0.0') ?? 0.0)
291
+ : 0.0;
292
+ final double price = isTrade
293
+ ? (double.tryParse(item['price']?.toString() ?? '0.0') ?? 0.0)
294
+ : 0.0;
295
+ final double total = isTrade
296
+ ? (shares * price)
297
+ : (double.tryParse(item['total']?.toString() ?? '0.0') ?? 0.0);
290
298
 
291
- return DataRow(cells: [
292
- DataCell(Text(DateFormat('yyyy-MM-dd').format(tradeDate))),
293
- DataCell(Text(_formatDuration(tradeAge))),
294
- DataCell(Text(symbol)),
295
- DataCell(Text(type)),
296
- DataCell(isTrade ? Text(shares.toStringAsFixed(4)) : const Text('-')),
297
- DataCell(isTrade ? Text(_formatCurrency(price)) : const Text('-')),
298
- DataCell(Text(_formatCurrency(total))),
299
- DataCell(
300
- IconButton(
301
- icon: const Icon(Icons.delete, color: Colors.red),
302
- onPressed: () => _confirmAndDeleteItem(context, viewModel, id, isTrade),
303
- tooltip: 'Delete Item',
299
+ return DataRow(cells: [
300
+ DataCell(Text(DateFormat('yyyy-MM-dd').format(tradeDate))),
301
+ DataCell(Text(_formatDuration(tradeAge))),
302
+ DataCell(Text(symbol)),
303
+ DataCell(Text(type)),
304
+ DataCell(isTrade ? Text(shares.toStringAsFixed(4)) : const Text('-')),
305
+ DataCell(isTrade ? Text(_formatCurrency(price)) : const Text('-')),
306
+ DataCell(Text(_formatCurrency(total))),
307
+ DataCell(
308
+ IconButton(
309
+ icon: const Icon(Icons.delete, color: Colors.red),
310
+ onPressed: () =>
311
+ _confirmAndDeleteItem(context, viewModel, id, isTrade),
312
+ tooltip: 'Delete Item',
313
+ ),
304
314
  ),
305
- ),
306
- ]);
307
- }).toList(),
315
+ ]);
316
+ }).toList(),
317
+ ),
308
318
  );
309
319
  }
310
320
 
@@ -320,13 +330,11 @@ class InvestmentAccountScreen extends StatelessWidget {
320
330
  : await viewModel.deleteDividend(itemId);
321
331
 
322
332
  if (ScaffoldMessenger.of(context).mounted) {
323
- ScaffoldMessenger.of(context).showSnackBar(
324
- SnackBar(
325
- content: Text(success
326
- ? 'The $itemType was deleted successfully.'
327
- : 'Failed to delete the $itemType.'),
328
- ),
329
- );
333
+ if (success) {
334
+ showSuccessSnackBar(context, 'The $itemType was deleted successfully.');
335
+ } else {
336
+ showErrorSnackBar(context, 'Failed to delete the $itemType.');
337
+ }
330
338
  }
331
339
  }
332
340
  }
@@ -3,6 +3,8 @@ import 'package:intl/intl.dart';
3
3
  import 'package:provider/provider.dart';
4
4
  import 'package:personal_finance_frontend_core_services/providers/auth_provider.dart';
5
5
  import 'package:personal_finance_frontend_core_ui/utils/app_dialogs.dart';
6
+ import 'package:personal_finance_frontend_core_ui/utils/app_responsive.dart';
7
+ import 'package:personal_finance_frontend_core_ui/utils/app_snackbars.dart';
6
8
  import 'package:personal_finance_frontend_core_ui/widgets/rrsp_contribution_form.dart';
7
9
  import '../viewmodels/rrsp_sun_life_viewmodel.dart';
8
10
 
@@ -99,8 +101,9 @@ class RrspSunLifeScreen extends StatelessWidget {
99
101
  final double unrealizedPL = double.tryParse(summary['unrealized_pl']?.toString() ?? '0.0') ?? 0.0;
100
102
  final plColor = (unrealizedPL >= 0) ? Colors.green : Colors.red;
101
103
 
102
- return DataTable(
103
- columns: const [
104
+ return ResponsiveHorizontalScroll(
105
+ child: DataTable(
106
+ columns: const [
104
107
  DataColumn(label: Text('User Contr.')),
105
108
  DataColumn(label: Text('Company Contr.')),
106
109
  DataColumn(label: Text('Total Contributed')),
@@ -109,7 +112,7 @@ class RrspSunLifeScreen extends StatelessWidget {
109
112
  DataColumn(label: Text('Market Value')),
110
113
  DataColumn(label: Text('Portfolio %')),
111
114
  ],
112
- rows: [
115
+ rows: [
113
116
  DataRow(
114
117
  cells: [
115
118
  DataCell(
@@ -132,7 +135,8 @@ class RrspSunLifeScreen extends StatelessWidget {
132
135
  ),
133
136
  ],
134
137
  ),
135
- ],
138
+ ],
139
+ ),
136
140
  );
137
141
  }
138
142
 
@@ -147,8 +151,9 @@ class RrspSunLifeScreen extends StatelessWidget {
147
151
  );
148
152
  }
149
153
 
150
- return DataTable(
151
- columns: const [
154
+ return ResponsiveHorizontalScroll(
155
+ child: DataTable(
156
+ columns: const [
152
157
  DataColumn(label: Text('Date')),
153
158
  DataColumn(label: Text('User Contr.')),
154
159
  DataColumn(label: Text('Company Contr.')),
@@ -159,7 +164,7 @@ class RrspSunLifeScreen extends StatelessWidget {
159
164
  DataColumn(label: Text('Portfolio %')),
160
165
  DataColumn(label: Text('Actions')),
161
166
  ],
162
- rows: viewModel.contributions.map((c) {
167
+ rows: viewModel.contributions.map((c) {
163
168
  final contributionId = c['id'] as int;
164
169
  final rrspAmount = double.tryParse(c['rrsp_amount']?.toString() ?? '0.0') ?? 0.0;
165
170
  final dpspAmount = double.tryParse(c['dpsp_amount']?.toString() ?? '0.0') ?? 0.0;
@@ -206,7 +211,8 @@ class RrspSunLifeScreen extends StatelessWidget {
206
211
  ),
207
212
  ],
208
213
  );
209
- }).toList(),
214
+ }).toList(),
215
+ ),
210
216
  );
211
217
  }
212
218
 
@@ -220,14 +226,12 @@ class RrspSunLifeScreen extends StatelessWidget {
220
226
  if (confirm == true) {
221
227
  final success = await viewModel.deleteContribution(contributionId);
222
228
  if (ScaffoldMessenger.of(context).mounted) {
223
- ScaffoldMessenger.of(context).showSnackBar(
224
- SnackBar(
225
- content: Text(success
226
- ? 'Contribution deleted successfully.'
227
- : 'Failed to delete contribution.'),
228
- ),
229
- );
229
+ if (success) {
230
+ showSuccessSnackBar(context, 'Contribution deleted successfully.');
231
+ } else {
232
+ showErrorSnackBar(context, 'Failed to delete contribution.');
233
+ }
230
234
  }
231
235
  }
232
236
  }
233
- }
237
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marcos_feitoza/personal-finance-frontend-feature-investments",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },