@marcos_feitoza/personal-finance-frontend-core-ui 1.2.0 → 1.2.1
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,10 @@
|
|
|
1
|
+
## [1.2.1](https://github.com/MarcosOps/personal-finance-frontend-core-ui/compare/v1.2.0...v1.2.1) (2026-01-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Web responsivo (mobile/tablet/resize) ([dba28a4](https://github.com/MarcosOps/personal-finance-frontend-core-ui/commit/dba28a4c370aac6f02a0e304e25c6eebaca4b961))
|
|
7
|
+
|
|
1
8
|
# [1.2.0](https://github.com/MarcosOps/personal-finance-frontend-core-ui/compare/v1.1.0...v1.2.0) (2026-01-29)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -10,17 +10,17 @@ class AppDialogs {
|
|
|
10
10
|
context: context,
|
|
11
11
|
builder: (BuildContext context) {
|
|
12
12
|
return AlertDialog(
|
|
13
|
-
title: const Text('
|
|
13
|
+
title: const Text('Confirm Deletion'),
|
|
14
14
|
content: Text(
|
|
15
|
-
'
|
|
15
|
+
'Are you sure you want to delete "$itemName"? This action cannot be undone.'),
|
|
16
16
|
actions: <Widget>[
|
|
17
17
|
TextButton(
|
|
18
18
|
onPressed: () => Navigator.of(context).pop(false),
|
|
19
|
-
child: const Text('
|
|
19
|
+
child: const Text('Cancel'),
|
|
20
20
|
),
|
|
21
21
|
TextButton(
|
|
22
22
|
onPressed: () => Navigator.of(context).pop(true),
|
|
23
|
-
child: const Text('
|
|
23
|
+
child: const Text('Delete'),
|
|
24
24
|
),
|
|
25
25
|
],
|
|
26
26
|
);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import 'package:flutter/widgets.dart';
|
|
2
|
+
|
|
3
|
+
/// Simple responsive helpers and breakpoints.
|
|
4
|
+
///
|
|
5
|
+
/// Why this exists:
|
|
6
|
+
/// - Most of the app was built desktop-first (many wide `Row`s and `DataTable`s).
|
|
7
|
+
/// - On mobile/tablet or when resizing the browser, layouts overflow.
|
|
8
|
+
/// - These helpers give us one place to define breakpoints and common patterns.
|
|
9
|
+
///
|
|
10
|
+
/// Breakpoints (can be adjusted later):
|
|
11
|
+
/// - mobile: < 600
|
|
12
|
+
/// - tablet: 600 .. < 1024
|
|
13
|
+
/// - desktop: >= 1024
|
|
14
|
+
class AppBreakpoints {
|
|
15
|
+
AppBreakpoints._();
|
|
16
|
+
|
|
17
|
+
static const double mobile = 600;
|
|
18
|
+
static const double tablet = 1024;
|
|
19
|
+
|
|
20
|
+
static bool isMobileWidth(double width) => width < mobile;
|
|
21
|
+
static bool isTabletWidth(double width) => width >= mobile && width < tablet;
|
|
22
|
+
static bool isDesktopWidth(double width) => width >= tablet;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Builds different widgets depending on the current available width.
|
|
26
|
+
class ResponsiveBuilder extends StatelessWidget {
|
|
27
|
+
final Widget Function(BuildContext context) mobile;
|
|
28
|
+
final Widget Function(BuildContext context)? tablet;
|
|
29
|
+
final Widget Function(BuildContext context) desktop;
|
|
30
|
+
|
|
31
|
+
const ResponsiveBuilder({
|
|
32
|
+
super.key,
|
|
33
|
+
required this.mobile,
|
|
34
|
+
this.tablet,
|
|
35
|
+
required this.desktop,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
@override
|
|
39
|
+
Widget build(BuildContext context) {
|
|
40
|
+
return LayoutBuilder(
|
|
41
|
+
builder: (context, constraints) {
|
|
42
|
+
final width = constraints.maxWidth;
|
|
43
|
+
|
|
44
|
+
if (AppBreakpoints.isMobileWidth(width)) {
|
|
45
|
+
return mobile(context);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (AppBreakpoints.isTabletWidth(width)) {
|
|
49
|
+
return (tablet ?? desktop)(context);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return desktop(context);
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Wraps a wide widget (like DataTable) with horizontal scroll when needed.
|
|
59
|
+
///
|
|
60
|
+
/// On desktop the widget is rendered normally.
|
|
61
|
+
/// On mobile/tablet we enable horizontal scrolling to avoid overflow.
|
|
62
|
+
class ResponsiveHorizontalScroll extends StatelessWidget {
|
|
63
|
+
final Widget child;
|
|
64
|
+
|
|
65
|
+
const ResponsiveHorizontalScroll({super.key, required this.child});
|
|
66
|
+
|
|
67
|
+
@override
|
|
68
|
+
Widget build(BuildContext context) {
|
|
69
|
+
return LayoutBuilder(
|
|
70
|
+
builder: (context, constraints) {
|
|
71
|
+
final width = constraints.maxWidth;
|
|
72
|
+
final needsScroll = !AppBreakpoints.isDesktopWidth(width);
|
|
73
|
+
|
|
74
|
+
if (!needsScroll) return child;
|
|
75
|
+
|
|
76
|
+
return SingleChildScrollView(
|
|
77
|
+
scrollDirection: Axis.horizontal,
|
|
78
|
+
child: ConstrainedBox(
|
|
79
|
+
// Make sure the child has at least the current width.
|
|
80
|
+
constraints: BoxConstraints(minWidth: width),
|
|
81
|
+
child: child,
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
|
+
import 'package:personal_finance_frontend_core_ui/utils/app_responsive.dart';
|
|
2
3
|
|
|
3
4
|
/// A reusable widget to display historical data in a standardized DataTable.
|
|
4
5
|
class HistoricalDataTable extends StatelessWidget {
|
|
@@ -24,8 +25,7 @@ class HistoricalDataTable extends StatelessWidget {
|
|
|
24
25
|
);
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
return
|
|
28
|
-
scrollDirection: Axis.horizontal,
|
|
28
|
+
return ResponsiveHorizontalScroll(
|
|
29
29
|
child: DataTable(
|
|
30
30
|
columnSpacing: 24.0,
|
|
31
31
|
columns: columns,
|