- created snackbar, step indicator, money text, text field and progress bar components.
- created wallet balance block, wallet item and kid line chart widgets. - restructured onboarding, signup and device signup screens into layouts and main screens. - updated signup and kid wallet screens to 17/11 design.
This commit is contained in:
@@ -1,2 +1,7 @@
|
||||
export 'src/theme/theme_port.dart';
|
||||
export 'src/theme/theme_sf_adapter.dart';
|
||||
export 'src/steps/step_indicator.dart';
|
||||
export 'src/texts/money_text.dart';
|
||||
export 'src/progress_bars/progress_bar.dart';
|
||||
export 'src/inputs/textfields.dart';
|
||||
export 'src/snackbars/snackbar.dart';
|
||||
72
packages/design_system/lib/src/inputs/textfields.dart
Normal file
72
packages/design_system/lib/src/inputs/textfields.dart
Normal file
@@ -0,0 +1,72 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class CustomTextField extends ConsumerStatefulWidget{
|
||||
bool? showPassword;
|
||||
final bool numeric;
|
||||
final String hint;
|
||||
final String label;
|
||||
final int? lines;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final int? length;
|
||||
|
||||
CustomTextField({
|
||||
super.key,
|
||||
this.showPassword,
|
||||
this.numeric = false,
|
||||
this.hint = '',
|
||||
this.label = '',
|
||||
this.lines,
|
||||
this.length,
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<CustomTextField> createState() => CustomTextFieldState();
|
||||
}
|
||||
|
||||
class CustomTextFieldState extends ConsumerState<CustomTextField>{
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return TextFormField(
|
||||
keyboardType: widget.numeric? TextInputType.number : TextInputType.text,
|
||||
obscureText: !(widget.showPassword ?? true),
|
||||
enableSuggestions: widget.showPassword ?? true,
|
||||
autocorrect: !(widget.showPassword ?? false),
|
||||
style: TextStyle(color: theme.getColorFor(ThemeCode.buttonSecondary)),
|
||||
inputFormatters: widget.numeric? [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
] : [],
|
||||
decoration: InputDecoration(
|
||||
counterText: "",
|
||||
hintText: widget.hint,
|
||||
labelText: widget.label,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
borderSide: BorderSide(color: theme.getColorFor(ThemeCode.textPrimary)),
|
||||
gapPadding: 16
|
||||
),
|
||||
suffixIcon: widget.showPassword!=null ? IconButton(
|
||||
icon: Icon(widget.showPassword!
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
widget.showPassword = !widget.showPassword!;
|
||||
});
|
||||
},
|
||||
) : null,
|
||||
),
|
||||
minLines: widget.lines ?? 1,
|
||||
maxLines: widget.lines ?? 1,
|
||||
maxLength: widget.length,
|
||||
onChanged: widget.onChanged ?? (_)=>{},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ProgressBar extends ConsumerWidget{
|
||||
final double max;
|
||||
final double value;
|
||||
final double height;
|
||||
final double textSize;
|
||||
final double textSecondarySize;
|
||||
final Color backgroundColor;
|
||||
final Color foregroundColor;
|
||||
final Color textColor;
|
||||
|
||||
const ProgressBar(
|
||||
this.max,
|
||||
this.value,
|
||||
this.height,
|
||||
this.textSize,
|
||||
this.textSecondarySize,
|
||||
this.backgroundColor,
|
||||
this.foregroundColor,
|
||||
this.textColor,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
||||
return
|
||||
Stack(
|
||||
children: [
|
||||
LinearProgressIndicator(
|
||||
value: value / max,
|
||||
minHeight: height,
|
||||
borderRadius: BorderRadius.all(Radius.circular(24)),
|
||||
color: foregroundColor,
|
||||
backgroundColor: backgroundColor
|
||||
),
|
||||
FractionallySizedBox(
|
||||
widthFactor: value / max,
|
||||
child: SizedBox(
|
||||
height: height,
|
||||
child: Center(
|
||||
child: MoneyText(
|
||||
text: "$value€",
|
||||
size: textSize,
|
||||
secondarySize: textSecondarySize,
|
||||
color: textColor,
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
65
packages/design_system/lib/src/snackbars/snackbar.dart
Normal file
65
packages/design_system/lib/src/snackbars/snackbar.dart
Normal file
@@ -0,0 +1,65 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
enum MessageType {
|
||||
info,
|
||||
error,
|
||||
warning,
|
||||
success
|
||||
}
|
||||
|
||||
class CustomSnackBar extends ConsumerWidget{
|
||||
final MessageType type;
|
||||
final String message;
|
||||
|
||||
CustomSnackBar({
|
||||
super.key,
|
||||
this.type = MessageType.info,
|
||||
required this.message,
|
||||
});
|
||||
|
||||
@override
|
||||
SnackBar build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
late final Color foregroundColor;
|
||||
late final Color backgroundColor;
|
||||
late final IconData icon;
|
||||
|
||||
switch (type){
|
||||
case MessageType.info:
|
||||
backgroundColor = Color(0xFFE3EFFD);
|
||||
foregroundColor = Color(0xFF1F4ECF);
|
||||
icon = Icons.info;
|
||||
case MessageType.error:
|
||||
backgroundColor = Color(0xFFFBEDE9);
|
||||
foregroundColor = Color(0xFFD12D00);
|
||||
icon = Icons.cancel;
|
||||
case MessageType.warning:
|
||||
backgroundColor = Color(0xFFFBF3E2);
|
||||
foregroundColor = Color(0xFFE34B04);
|
||||
icon = Icons.warning_outlined;
|
||||
case MessageType.success:
|
||||
backgroundColor = Color(0xFFE2F4E8);
|
||||
foregroundColor = Color(0xFF00713D);
|
||||
icon = Icons.check_circle;
|
||||
}
|
||||
|
||||
return SnackBar(
|
||||
behavior: SnackBarBehavior.floating,
|
||||
backgroundColor: backgroundColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(color: foregroundColor, width: 1),
|
||||
borderRadius: BorderRadius.all(Radius.circular(10))
|
||||
),
|
||||
content: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(icon, color: foregroundColor),
|
||||
Expanded(child: Text(message, style: TextStyle(color: theme.getColorFor(ThemeCode.textPrimary), fontSize: 14)))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
29
packages/design_system/lib/src/steps/step_indicator.dart
Normal file
29
packages/design_system/lib/src/steps/step_indicator.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StepIndicator extends StatelessWidget{
|
||||
final int max;
|
||||
final int current;
|
||||
final Color color;
|
||||
|
||||
const StepIndicator({super.key, required this.max, required this.current, required this.color});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
Spacer(),
|
||||
...List<Widget>.generate(max, (int index){
|
||||
return DecoratedBox(
|
||||
decoration: ShapeDecoration(
|
||||
shape: CircleBorder(side: BorderSide(color: color)),
|
||||
color: (index < current)? color: Colors.transparent
|
||||
),
|
||||
child: SizedBox(width: 16, height: 16),
|
||||
);
|
||||
}),
|
||||
Spacer()
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
43
packages/design_system/lib/src/texts/money_text.dart
Normal file
43
packages/design_system/lib/src/texts/money_text.dart
Normal file
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MoneyText extends StatelessWidget {
|
||||
final String text;
|
||||
final double size;
|
||||
final double? secondarySize;
|
||||
final Color color;
|
||||
final double height;
|
||||
|
||||
const MoneyText({
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.size,
|
||||
this.secondarySize,
|
||||
required this.color,
|
||||
this.height = 1,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final units = text.split(".")[0];
|
||||
final cents = ",${text.split(".")[1]}";
|
||||
|
||||
return Text.rich(TextSpan(
|
||||
text: units,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: size,
|
||||
color: color,
|
||||
height: height
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: cents,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: secondarySize ?? size,
|
||||
)
|
||||
)
|
||||
]
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ enum ThemeCode {
|
||||
abstract class ThemePort {
|
||||
late Map<ThemeCode, Color> theme;
|
||||
late List<List<Color>> cardColors;
|
||||
late List<Color> disabledCardColors;
|
||||
|
||||
Color getColorFor(ThemeCode code) {
|
||||
Color? c = theme[code];
|
||||
@@ -37,4 +38,8 @@ abstract class ThemePort {
|
||||
List<Color> getCardColorFor(int index) {
|
||||
return cardColors[index % cardColors.length];
|
||||
}
|
||||
|
||||
List<Color> getDisabledCardColors() {
|
||||
return disabledCardColors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,11 @@ class ThemeSfAdapter extends ThemePort {
|
||||
|
||||
@override
|
||||
List<List<Color>> get cardColors => _cardColors;
|
||||
|
||||
final List<Color> _disabledCardColors = [
|
||||
Color(0xFF989797), Color(0xFF797676), Color(0xFF5F5A5A)
|
||||
];
|
||||
|
||||
@override
|
||||
List<Color> get disabledCardColors => _disabledCardColors;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ dependencies:
|
||||
sdk: flutter
|
||||
flutter_riverpod: ^3.0.3
|
||||
get_it: ^9.0.5
|
||||
fonts:
|
||||
path: ../../packages/fonts
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
20
packages/fonts/pubspec.yaml
Normal file
20
packages/fonts/pubspec.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
name: fonts
|
||||
# resolution: workspace
|
||||
description: "A new Flutter package project."
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
fonts:
|
||||
- family: Stolzl
|
||||
fonts:
|
||||
- asset: lib/fonts/stolzl_regular.otf
|
||||
- asset: lib/fonts/stolzl_bold.otf
|
||||
weight: 500
|
||||
@@ -4,3 +4,4 @@ export 'src/widgets/deposit_block.dart';
|
||||
export 'src/screens/connection_error_screen.dart';
|
||||
export 'src/screens/server_error_screen.dart';
|
||||
export 'src/screens/no_plan_error_screen.dart';
|
||||
export 'src/widgets/wallet_balance_block.dart';
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class Kid {
|
||||
final String name;
|
||||
final double balance;
|
||||
final double savings;
|
||||
|
||||
const Kid({
|
||||
required this.name,
|
||||
required this.balance,
|
||||
|
||||
required this.savings,
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class DepositBlock extends ConsumerWidget {
|
||||
@@ -20,40 +19,56 @@ class DepositBlock extends ConsumerWidget {
|
||||
),
|
||||
margin: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Text(
|
||||
"Ingresar dinero en el wallet",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
"Ingresar dinero en el wallet",
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Cantidad",
|
||||
hintText: "0€",
|
||||
border: OutlineInputBorder(),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
label: "Cantidad",
|
||||
hint: "0€",
|
||||
numeric: true,
|
||||
),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
shape: WidgetStatePropertyAll(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(18))
|
||||
))
|
||||
),
|
||||
child: SizedBox(
|
||||
height: 60,
|
||||
child: Center(child: Text("Ingresar", style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500)))),
|
||||
),
|
||||
],
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
),
|
||||
child: Text("Ingresar"),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Icon(Icons.info_outline, size: 16),
|
||||
Text("Máximo que puedes añadir: $max€"),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text("Máximo que puedes añadir: $max€"),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -4,10 +4,7 @@ import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class LineGraph extends ConsumerStatefulWidget {
|
||||
final lines = [
|
||||
[0, 1, 0, 1, 0, 1, 0],
|
||||
[1, 0, 1, 0, 1, 0, 1],
|
||||
];
|
||||
final lines = [[0,1,0,1,0,1,0],[1,0,1,0,1,0,1]];
|
||||
|
||||
LineGraph({super.key});
|
||||
|
||||
@@ -16,7 +13,8 @@ class LineGraph extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class LineGraphState extends ConsumerState<LineGraph> {
|
||||
final weekDays = ["L", "M", "X", "J", "V", "S", "D"];
|
||||
|
||||
final weekDays = ["L", "M", "X", "J", "V", "S", "D"];
|
||||
String? timeSpan;
|
||||
late var days = weekDays;
|
||||
|
||||
@@ -31,148 +29,146 @@ class LineGraphState extends ConsumerState<LineGraph> {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(15),
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
border: BoxBorder.fromLTRB(
|
||||
left: BorderSide(color: Colors.cyan, width: 5),
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
border: BoxBorder.fromLTRB(left: BorderSide(color: Colors.cyan, width: 5)),
|
||||
borderRadius: BorderRadius.all(Radius.circular(13)),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary)
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
spacing: 32,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text("Gastos", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Spacer(),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
),
|
||||
child: DropdownButton(
|
||||
underline: Container(),
|
||||
value: timeSpan,
|
||||
onChanged: (String? value) {
|
||||
setState(() {
|
||||
timeSpan = value;
|
||||
});
|
||||
Row(children: [
|
||||
Text("Gastos", style: TextStyle(fontWeight: FontWeight.w500, fontSize: 18)),
|
||||
Spacer(),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
),
|
||||
child: DropdownButton(
|
||||
underline: Container(),
|
||||
value: timeSpan,
|
||||
onChanged: (String? value) {
|
||||
setState(() {
|
||||
timeSpan = value;
|
||||
});
|
||||
},
|
||||
dropdownColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
items: [
|
||||
DropdownMenuItem(value: "day", child: Text("Hoy", style: TextStyle(fontSize: 14, letterSpacing: 0))),
|
||||
DropdownMenuItem(value: "week", child: Text("Esta semana", style: TextStyle(fontSize: 14, letterSpacing: 0))),
|
||||
DropdownMenuItem(value: "month", child: Text("Este mes", style: TextStyle(fontSize: 14, letterSpacing: 0))),
|
||||
]
|
||||
),
|
||||
)
|
||||
]),
|
||||
SizedBox(
|
||||
height: 160,
|
||||
child: LineChart(LineChartData(
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
drawHorizontalLine: false,
|
||||
drawVerticalLine: true,
|
||||
verticalInterval: 1,
|
||||
getDrawingVerticalLine: (value)=>FlLine(strokeWidth: 43, color: theme.getColorFor(ThemeCode.backgroundSecondary))
|
||||
),
|
||||
titlesData: FlTitlesData(
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
interval: 1,
|
||||
showTitles: true,
|
||||
reservedSize: 40,
|
||||
getTitlesWidget: (double value, TitleMeta meta){
|
||||
String text = weekDays[value.toInt()];
|
||||
|
||||
return SideTitleWidget(
|
||||
space: 4,
|
||||
meta: meta,
|
||||
child: Expanded(child: Center(child: Text(text, style: TextStyle(fontSize: 12)))),
|
||||
);
|
||||
},
|
||||
dropdownColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
items: [
|
||||
DropdownMenuItem(value: "day", child: Text("Hoy")),
|
||||
DropdownMenuItem(value: "week", child: Text("Esta semana")),
|
||||
DropdownMenuItem(value: "month", child: Text("Este mes")),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: LineChart(
|
||||
LineChartData(
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
drawHorizontalLine: false,
|
||||
drawVerticalLine: true,
|
||||
verticalInterval: 1,
|
||||
leftTitles: AxisTitles(),
|
||||
topTitles: AxisTitles(),
|
||||
rightTitles: AxisTitles()
|
||||
),
|
||||
lineTouchData: LineTouchData(
|
||||
touchTooltipData: LineTouchTooltipData(
|
||||
tooltipBorderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
getTooltipColor: (spot) => theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
getTooltipItems: (List<LineBarSpot> touchedSpots) {
|
||||
return touchedSpots.map((LineBarSpot touchedSpot) {
|
||||
return LineTooltipItem(
|
||||
"${touchedSpot.y}€",
|
||||
TextStyle(fontWeight: FontWeight.w500, fontSize: 14, color: theme.getColorFor(ThemeCode.textSecondary)),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
),
|
||||
getTouchedSpotIndicator: (
|
||||
_,
|
||||
indicators,
|
||||
) {
|
||||
return indicators
|
||||
.map((int index) => const TouchedSpotIndicatorData(
|
||||
FlLine(color: Colors.transparent),
|
||||
FlDotData(show: false),
|
||||
))
|
||||
.toList();
|
||||
},
|
||||
touchSpotThreshold: 25,
|
||||
distanceCalculator:
|
||||
(Offset touchPoint, Offset spotPixelCoordinates) =>
|
||||
(touchPoint - spotPixelCoordinates).distance,
|
||||
),
|
||||
borderData: FlBorderData(
|
||||
show: true,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Colors.lightBlue.withValues(alpha: 0.2),
|
||||
width: 4
|
||||
),
|
||||
titlesData: FlTitlesData(
|
||||
//show: false,
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: 40,
|
||||
getTitlesWidget: (double value, TitleMeta meta) =>
|
||||
SideTitleWidget(
|
||||
space: 4,
|
||||
meta: meta,
|
||||
/*fitInside: fitInsideBottomTitle
|
||||
? SideTitleFitInsideData.fromTitleMeta(meta, distanceFromEdge: 0)
|
||||
: SideTitleFitInsideData.disable(),*/
|
||||
child: Text(weekDays[value.toInt()]),
|
||||
),
|
||||
),
|
||||
),
|
||||
leftTitles: AxisTitles(),
|
||||
topTitles: AxisTitles(),
|
||||
rightTitles: AxisTitles(),
|
||||
),
|
||||
lineTouchData: LineTouchData(
|
||||
touchTooltipData: LineTouchTooltipData(
|
||||
getTooltipColor: (touchedSpot) =>
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
getTooltipItems: (List<LineBarSpot> touchedBarSpots) {
|
||||
return touchedBarSpots.map((barSpot) {
|
||||
return LineTooltipItem(
|
||||
"${barSpot.y} €",
|
||||
TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.textSecondary),
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
),
|
||||
),
|
||||
borderData: FlBorderData(
|
||||
show: true,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Colors.lightBlue.withValues(alpha: 0.2),
|
||||
width: 4,
|
||||
),
|
||||
left: const BorderSide(color: Colors.transparent),
|
||||
right: const BorderSide(color: Colors.transparent),
|
||||
top: const BorderSide(color: Colors.transparent),
|
||||
),
|
||||
),
|
||||
lineBarsData: [
|
||||
LineChartBarData(
|
||||
isCurved: true,
|
||||
color: Colors.pink,
|
||||
barWidth: 5,
|
||||
isStrokeCapRound: true,
|
||||
dotData: const FlDotData(show: false),
|
||||
belowBarData: BarAreaData(show: false),
|
||||
spots: const [
|
||||
FlSpot(0, 1),
|
||||
FlSpot(1, 0),
|
||||
FlSpot(2, 1),
|
||||
FlSpot(3, 0),
|
||||
FlSpot(4, 1),
|
||||
FlSpot(5, 0),
|
||||
FlSpot(6, 1),
|
||||
],
|
||||
),
|
||||
LineChartBarData(
|
||||
isCurved: true,
|
||||
color: Colors.cyan,
|
||||
barWidth: 5,
|
||||
isStrokeCapRound: true,
|
||||
dotData: const FlDotData(show: false),
|
||||
belowBarData: BarAreaData(show: false),
|
||||
spots: const [
|
||||
FlSpot(0, 0),
|
||||
FlSpot(1, 1),
|
||||
FlSpot(2, 0),
|
||||
FlSpot(3, 1),
|
||||
FlSpot(4, 0),
|
||||
FlSpot(5, 1),
|
||||
FlSpot(6, 0),
|
||||
],
|
||||
),
|
||||
],
|
||||
minX: 0,
|
||||
maxX: days.length - 1,
|
||||
maxY: 1,
|
||||
minY: 0,
|
||||
left: const BorderSide(color: Colors.transparent),
|
||||
right: const BorderSide(color: Colors.transparent),
|
||||
top: const BorderSide(color: Colors.transparent),
|
||||
),
|
||||
),
|
||||
),
|
||||
lineBarsData: [
|
||||
LineChartBarData(
|
||||
isCurved: true,
|
||||
color: Colors.pink,
|
||||
barWidth: 5,
|
||||
isStrokeCapRound: true,
|
||||
dotData: const FlDotData(show: false),
|
||||
belowBarData: BarAreaData(show: false),
|
||||
spots: List<FlSpot>.generate(days.length, (int index){
|
||||
return FlSpot(index.toDouble(), (index+1)%2);
|
||||
})
|
||||
),
|
||||
LineChartBarData(
|
||||
isCurved: true,
|
||||
color: Colors.cyan,
|
||||
barWidth: 5,
|
||||
isStrokeCapRound: true,
|
||||
dotData: const FlDotData(show: false),
|
||||
belowBarData: BarAreaData(show: false),
|
||||
spots: List<FlSpot>.generate(days.length, (int index){
|
||||
return FlSpot(index.toDouble(), index%2);
|
||||
})
|
||||
),
|
||||
],
|
||||
minX: 0,
|
||||
maxX: days.length-1,
|
||||
maxY: 1,
|
||||
minY: 0,
|
||||
))
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
59
packages/sf_shared/lib/src/widgets/wallet_balance_block.dart
Normal file
59
packages/sf_shared/lib/src/widgets/wallet_balance_block.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class WalletBalanceBlock extends ConsumerWidget {
|
||||
final double max;
|
||||
final double value;
|
||||
final double savings;
|
||||
final double savingsPlan;
|
||||
|
||||
const WalletBalanceBlock({
|
||||
super.key,
|
||||
required this.max,
|
||||
required this.value,
|
||||
required this.savings,
|
||||
this.savingsPlan = 30.0
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"Wallet",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
MoneyText(
|
||||
text: "$max€ total",
|
||||
size: 26,
|
||||
secondarySize: 16,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(children: [
|
||||
Text("Objetivos de ahorro"),
|
||||
Spacer(),
|
||||
Text("$savingsPlan€")
|
||||
]),
|
||||
ProgressBar(savingsPlan, savings, 24, 16, 12, theme.getColorFor(ThemeCode.backgroundSecondary), theme.getColorFor(ThemeCode.backgroundTertiary), theme.getColorFor(ThemeCode.textPrimary)),
|
||||
ProgressBar(max, value, 83, 40, 24, theme.getColorFor(ThemeCode.backgroundTertiary), theme.getColorFor(ThemeCode.buttonPrimary), theme.getColorFor(ThemeCode.textSecondary)),
|
||||
Center(child: Text("Disponible")),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user