From 247c062b526c7ed16b9d916e3155e2baebef379c Mon Sep 17 00:00:00 2001 From: Enzo Date: Thu, 16 Nov 2023 11:36:04 +0100 Subject: [PATCH] affichage home view --- lib/common_widget/container_stats.dart | 56 + lib/common_widget/ligne_container_stats.dart | 31 + lib/common_widget/stats.dart | 4 +- lib/common_widget/steps.dart | 2 - lib/main.dart | 3 +- lib/modele/activity.dart | 97 +- lib/modele/user.dart | 3 +- lib/view/activity/activity.dart | 22 +- lib/view/home/home_view.dart | 22 +- .../home/mobile/mobile_Activity_view.dart | 4 - lib/view/home/mobile/mobile_homeview.dart | 616 ++-------- lib/view/ne_pas_supprimer/home_view.txt | 1050 +++++++++++++++++ 12 files changed, 1310 insertions(+), 600 deletions(-) create mode 100644 lib/common_widget/container_stats.dart create mode 100644 lib/common_widget/ligne_container_stats.dart create mode 100644 lib/view/ne_pas_supprimer/home_view.txt diff --git a/lib/common_widget/container_stats.dart b/lib/common_widget/container_stats.dart new file mode 100644 index 0000000..c18f603 --- /dev/null +++ b/lib/common_widget/container_stats.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class ContainerStats extends StatelessWidget { + const ContainerStats(this.value, this.designation, {Key? key}) + : super(key: key); + + final String value; + final String designation; + + @override + Widget build(BuildContext context) { + return Container( + height: 110, + width: 110, + padding: const EdgeInsets.all(8), + margin: const EdgeInsets.symmetric(vertical: 5), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + color: const Color(0xffe1e1e1), + ), + boxShadow: const [ + BoxShadow( + color: Colors.black12, + offset: Offset(3, 3), + blurRadius: 3, + ), + ]), + child: Stack( + children: [ + Align( + alignment: Alignment.bottomLeft, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + designation, + style: const TextStyle(fontSize: 10), + ), + Text( + value, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w800, + ), + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/common_widget/ligne_container_stats.dart b/lib/common_widget/ligne_container_stats.dart new file mode 100644 index 0000000..3530c38 --- /dev/null +++ b/lib/common_widget/ligne_container_stats.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:smartfit_app_mobile/common_widget/container_stats.dart'; + +class LigneContainerStats extends StatelessWidget { + const LigneContainerStats(this.value1, this.value2, this.value3, + this.designation1, this.designation2, this.designation3, + {Key? key}) + : super(key: key); + + final String value1; + final String value2; + final String value3; + + final String designation1; + final String designation2; + final String designation3; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + const SizedBox(height: 10), + ContainerStats(value1, designation1), + const SizedBox(height: 10), + ContainerStats(value2, designation2), + const SizedBox(height: 10), + ContainerStats(value3, designation3), + ], + ); + } +} diff --git a/lib/common_widget/stats.dart b/lib/common_widget/stats.dart index 32e9264..977eb0b 100644 --- a/lib/common_widget/stats.dart +++ b/lib/common_widget/stats.dart @@ -24,7 +24,7 @@ class Stats extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 30), child: Row( children: [ - Text( + const Text( 'Statistiques', style: TextStyle( fontSize: 14, @@ -45,7 +45,7 @@ class Stats extends StatelessWidget { scrollDirection: Axis.horizontal, child: Row( children: [ - SizedBox(width: 30), + const SizedBox(width: 30), InfoStat( icon: Icons.timer, iconColor: Color.fromARGB(255, 255, 255, 255), diff --git a/lib/common_widget/steps.dart b/lib/common_widget/steps.dart index 370785d..5bee49f 100644 --- a/lib/common_widget/steps.dart +++ b/lib/common_widget/steps.dart @@ -7,8 +7,6 @@ class Steps extends StatelessWidget { @override Widget build(BuildContext context) { - print("lhwaa"); - String steps = Provider.of(context, listen: false) .listActivity[0] .getTotalSteps(); diff --git a/lib/main.dart b/lib/main.dart index 77fdfa7..28c7f13 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/view/login/signup_view.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart'; +import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart'; void main() { runApp(ChangeNotifierProvider( @@ -36,7 +37,7 @@ class MyApp extends StatelessWidget { primaryColor: TColor.primaryColor1, fontFamily: "Poppins"), //home: const StartedView(), - home: const SignUpView(), + home: const MainTabView(), ); } } diff --git a/lib/modele/activity.dart b/lib/modele/activity.dart index 605d8de..413f99e 100644 --- a/lib/modele/activity.dart +++ b/lib/modele/activity.dart @@ -5,6 +5,7 @@ class ActivityOfUser { late String _nomActivite; late String _imageName; late List _contentActivity; + late int _dataSession; List get contentActivity => _contentActivity; @@ -12,6 +13,18 @@ class ActivityOfUser { _nomActivite = nom; _imageName = "assets/img/workout1.svg"; _contentActivity = listeDynamic; + _dataSession = getDataSession(); + } + + // ----- Retourne l'indice de la ligne qui contient les données de la session -- // + int getDataSession() { + for (int i = _contentActivity.length - 1; i != 0; i--) { + if (_contentActivity[i][0] == "Data" && + _contentActivity[i][2] == "session") { + return i; + } + } + return 0; } List getHeartRateWithTime() { @@ -64,7 +77,6 @@ class ActivityOfUser { if (ligne.length >= 39 && ligne[0] == "Data" && ligne[39] == "total_calories") { - print(ligne[39]); if (firtTimeStamp == 0) { firtTimeStamp = ligne[4]; } @@ -77,77 +89,48 @@ class ActivityOfUser { } String getTotalSteps() { - print(_contentActivity.length); - for (int i = 0; - i < _contentActivity[_contentActivity.length - 3].length; - i++) { - print(_contentActivity[_contentActivity.length - 3][i]); - - if (_contentActivity[_contentActivity.length - 3][i] == "total_strides") { - return _contentActivity[_contentActivity.length - 3][i + 1].toString(); + for (int i = 0; i < _contentActivity[_dataSession].length; i++) { + if (_contentActivity[_dataSession][i] == "total_strides") { + return _contentActivity[_dataSession][i + 1].toString(); } } - return "NAN"; + return "null"; } String getTotalCalorie() { - print(_contentActivity.length); - for (int i = 0; - i < _contentActivity[_contentActivity.length - 3].length; - i++) { - print(_contentActivity[_contentActivity.length - 3][i]); - - if (_contentActivity[_contentActivity.length - 3][i] == - "total_calories") { - return _contentActivity[_contentActivity.length - 3][i + 1].toString(); + for (int i = 0; i < _contentActivity[_dataSession].length; i++) { + if (_contentActivity[_dataSession][i] == "total_calories") { + return _contentActivity[_dataSession][i + 1].toString(); } } - return "NAN"; + return "null"; } String getTotalAvgHeartRate() { - print(_contentActivity.length); - for (int i = 0; - i < _contentActivity[_contentActivity.length - 3].length; - i++) { - print(_contentActivity[_contentActivity.length - 3][i]); - - if (_contentActivity[_contentActivity.length - 3][i] == - "total_calories") { - return _contentActivity[_contentActivity.length - 3][i + 1].toString(); + for (int i = 0; i < _contentActivity[_dataSession].length; i++) { + if (_contentActivity[_dataSession][i] == "avg_heart_rate") { + return _contentActivity[_dataSession][i + 1].toString(); } } - return "NAN"; + return "null"; } String getTotalTime() { - print(_contentActivity.length); - for (int i = 0; - i < _contentActivity[_contentActivity.length - 3].length; - i++) { - print(_contentActivity[_contentActivity.length - 3][i]); - - if (_contentActivity[_contentActivity.length - 3][i] == - "total_elapsed_time") { - return _contentActivity[_contentActivity.length - 3][i + 1].toString(); + for (int i = 0; i < _contentActivity[_dataSession].length; i++) { + if (_contentActivity[_dataSession][i] == "total_elapsed_time") { + return _contentActivity[_dataSession][i + 1].toString(); } } - return "NAN"; + return "null"; } String getTotalDistance() { - print(_contentActivity.length); - for (int i = 0; - i < _contentActivity[_contentActivity.length - 3].length; - i++) { - print(_contentActivity[_contentActivity.length - 3][i]); - - if (_contentActivity[_contentActivity.length - 3][i] == - "total_distance") { - return _contentActivity[_contentActivity.length - 3][i + 1].toString(); + for (int i = 0; i < _contentActivity[_dataSession].length; i++) { + if (_contentActivity[_dataSession][i] == "total_distance") { + return _contentActivity[_dataSession][i + 1].toString(); } } - return "NAN"; + return "null"; } List getAltitudeWithTime() { @@ -167,20 +150,6 @@ class ActivityOfUser { return result; } - double getDistance() { - double result = 0.0; - for (int i = _contentActivity.length - 1; i >= 0; i--) { - if (_contentActivity[i].length >= 8 && - _contentActivity[i][0] == "Data" && - _contentActivity[i][6] == "distance") { - if (_contentActivity[i][7] > result) { - result = _contentActivity[i][7].toDouble(); - } - } - } - return result; - } - List getSpeedWithTime() { List result = List.empty(growable: true); int firtTimeStamp = 0; diff --git a/lib/modele/user.dart b/lib/modele/user.dart index 24d6d9b..d9715a8 100644 --- a/lib/modele/user.dart +++ b/lib/modele/user.dart @@ -5,10 +5,11 @@ class User extends ChangeNotifier { String username = "VOID"; String email = "VOID"; String token = "VOID"; - List listActivity = List.empty(); + List listActivity = List.empty(growable: true); void addActivity(ActivityOfUser activity) { listActivity.add(activity); + print("add"); notifyListeners(); } diff --git a/lib/view/activity/activity.dart b/lib/view/activity/activity.dart index 5198ab7..6e05af5 100644 --- a/lib/view/activity/activity.dart +++ b/lib/view/activity/activity.dart @@ -1,4 +1,6 @@ +import 'package:provider/provider.dart'; import 'package:responsive_builder/responsive_builder.dart'; +import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/view/home/mobile/mobile_Activity_view.dart'; import 'package:smartfit_app_mobile/view/home/web/web_Activity_view.dart'; import 'package:flutter/material.dart'; @@ -8,9 +10,21 @@ class Activity extends StatelessWidget { @override Widget build(BuildContext context) { - return ScreenTypeLayout.builder( - mobile: (_) => const MobileActivity(), - desktop: (_) => const WebActivity(), - ); + if (context.watch().listActivity.isEmpty) { + return const Scaffold( + body: Column( + children: [ + Text("C'est vide"), + Text("C'est vide"), + Text("C'est vide"), + Text("C'est vide") + ], + )); + } else { + return ScreenTypeLayout.builder( + mobile: (_) => const MobileActivity(), + desktop: (_) => const WebActivity(), + ); + } } } diff --git a/lib/view/home/home_view.dart b/lib/view/home/home_view.dart index 0b6f1cb..4695ac0 100644 --- a/lib/view/home/home_view.dart +++ b/lib/view/home/home_view.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:responsive_builder/responsive_builder.dart'; +import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/view/home/mobile/mobile_homeview.dart'; import 'package:smartfit_app_mobile/view/home/web/web_homeview.dart'; @@ -13,9 +15,21 @@ class HomeView extends StatefulWidget { class _HomeViewState extends State { @override Widget build(BuildContext context) { - return ScreenTypeLayout.builder( - mobile: (_) => const MobileHomeView(), - desktop: (_) => const WebHomeView(), - ); + if (context.watch().listActivity.isEmpty) { + return const Scaffold( + body: Column( + children: [ + Text("C'est vide"), + Text("C'est vide"), + Text("C'est vide"), + Text("C'est vide") + ], + )); + } else { + return ScreenTypeLayout.builder( + mobile: (_) => const MobileHomeView(), + desktop: (_) => const WebHomeView(), + ); + } } } diff --git a/lib/view/home/mobile/mobile_Activity_view.dart b/lib/view/home/mobile/mobile_Activity_view.dart index d42419e..17af619 100644 --- a/lib/view/home/mobile/mobile_Activity_view.dart +++ b/lib/view/home/mobile/mobile_Activity_view.dart @@ -11,10 +11,6 @@ class MobileActivity extends StatelessWidget { @override Widget build(BuildContext context) { - if (context.watch().listActivity.isEmpty) { - return const Scaffold(body: Text("C'est vide")); - } - return const Scaffold( backgroundColor: Colors.white, body: Column( diff --git a/lib/view/home/mobile/mobile_homeview.dart b/lib/view/home/mobile/mobile_homeview.dart index 196a0d5..6d23570 100644 --- a/lib/view/home/mobile/mobile_homeview.dart +++ b/lib/view/home/mobile/mobile_homeview.dart @@ -4,6 +4,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:simple_animation_progress_bar/simple_animation_progress_bar.dart'; import 'package:simple_circular_progress_bar/simple_circular_progress_bar.dart'; +import 'package:smartfit_app_mobile/common_widget/container_stats.dart'; +import 'package:smartfit_app_mobile/common_widget/ligne_container_stats.dart'; import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common_widget/round_button.dart'; @@ -18,9 +20,56 @@ class MobileHomeView extends StatefulWidget { } class _MobileHomeView extends State { - List showingTooltipOnSpots = [0]; + List bpmSecondes = [FlSpot(0, 30)]; + List bpmSecondes2 = []; + double calories = 0.0; + List vitesseSecondes = [FlSpot(0, 30)]; + List altitudeSecondes = [FlSpot(0, 30)]; + + TextEditingController bpmController = TextEditingController(); + + void normaliserDeuxiemeElement(List liste) { + // Trouver le plus grand élément dans la liste + double maxElement = 0.0; + for (var spot in liste) { + if (spot.y > maxElement) { + maxElement = spot.y; + } + } + + // Calculer le facteur de normalisation + double normalisationFactor = maxElement != 0.0 ? 100 / maxElement : 1.0; + + // Mettre à jour tous les éléments de la liste + for (int i = 0; i < liste.length; i++) { + liste[i] = FlSpot(liste[i].x, liste[i].y * normalisationFactor); + } + } - List allSpots = [const FlSpot(0, 20)]; + List lastWorkoutArr = [ + { + "name": "Full Body Workout", + "image": "assets/img/Workout1.png", + "kcal": "180", + "time": "20", + "progress": 0.3 + }, + { + "name": "Lower Body Workout", + "image": "assets/img/Workout2.png", + "kcal": "200", + "time": "30", + "progress": 0.4 + }, + { + "name": "Ab Workout", + "image": "assets/img/Workout3.png", + "kcal": "300", + "time": "40", + "progress": 0.7 + }, + ]; + List showingTooltipOnSpots = [0]; List waterArr = [ {"title": "6am - 8am", "subtitle": "600ml"}, @@ -33,12 +82,24 @@ class _MobileHomeView extends State { @override Widget build(BuildContext context) { var media = MediaQuery.of(context).size; - User user = context.watch(); + + bpmSecondes = + Provider.of(context).listActivity[0].getHeartRateWithTime(); + vitesseSecondes = + Provider.of(context).listActivity[0].getSpeedWithTime(); + altitudeSecondes = + Provider.of(context).listActivity[0].getAltitudeWithTime(); + calories = double.parse( + Provider.of(context).listActivity[0].getTotalCalorie()); + + normaliserDeuxiemeElement(vitesseSecondes); + normaliserDeuxiemeElement(altitudeSecondes); + bpmSecondes2 = List.from(bpmSecondes); + normaliserDeuxiemeElement(bpmSecondes2); final lineBarsData = [ LineChartBarData( - showingIndicators: showingTooltipOnSpots, - spots: allSpots, + spots: bpmSecondes, isCurved: false, barWidth: 2, belowBarData: BarAreaData( @@ -77,7 +138,7 @@ class _MobileHomeView extends State { style: TextStyle(color: TColor.gray, fontSize: 12), ), Text( - user.username, + "Benjelloun Othmane", style: TextStyle( color: TColor.black, fontSize: 20, @@ -105,123 +166,6 @@ class _MobileHomeView extends State { SizedBox( height: media.width * 0.05, ), - Container( - height: media.width * 0.4, - decoration: BoxDecoration( - gradient: LinearGradient(colors: TColor.primaryG), - borderRadius: BorderRadius.circular(media.width * 0.075)), - child: Stack(alignment: Alignment.center, children: [ - Image.asset( - "assets/img/bg_dots.png", - height: media.width * 0.4, - width: double.maxFinite, - fit: BoxFit.fitHeight, - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, horizontal: 25), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Graph 1", - style: TextStyle( - color: TColor.white, - fontSize: 14, - fontWeight: FontWeight.w700), - ), - Text( - "Sous titre 1", - style: TextStyle( - color: TColor.white.withOpacity(0.7), - fontSize: 12), - ), - SizedBox( - height: media.width * 0.05, - ), - SizedBox( - width: 120, - height: 35, - child: RoundButton( - title: "Voir plus", - type: RoundButtonType.bgSGradient, - fontSize: 12, - fontWeight: FontWeight.w400, - onPressed: () {})) - ], - ), - AspectRatio( - aspectRatio: 1, - child: PieChart( - PieChartData( - pieTouchData: PieTouchData( - touchCallback: - (FlTouchEvent event, pieTouchResponse) {}, - ), - startDegreeOffset: 250, - borderData: FlBorderData( - show: false, - ), - sectionsSpace: 1, - centerSpaceRadius: 0, - sections: showingSections(), - ), - ), - ), - ], - ), - ) - ]), - ), - SizedBox( - height: media.width * 0.05, - ), - Container( - padding: - const EdgeInsets.symmetric(vertical: 15, horizontal: 15), - decoration: BoxDecoration( - color: TColor.primaryColor2.withOpacity(0.3), - borderRadius: BorderRadius.circular(15), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Suivi d'activité", - style: TextStyle( - color: TColor.black, - fontSize: 14, - fontWeight: FontWeight.w700), - ), - SizedBox( - width: 70, - height: 25, - child: RoundButton( - title: "Voir", - type: RoundButtonType.bgGradient, - fontSize: 12, - fontWeight: FontWeight.w400, - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - const ActivityTrackerView(), - ), - ); - }, - ), - ) - ], - ), - ), - SizedBox( - height: media.width * 0.05, - ), Text( "Status d'activité", style: TextStyle( @@ -253,29 +197,23 @@ class _MobileHomeView extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Graph 2 ( rhythme cardiaque )", + "Rythme cardiaque", style: TextStyle( color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700), ), - ShaderMask( - blendMode: BlendMode.srcIn, - shaderCallback: (bounds) { - return LinearGradient( - colors: TColor.primaryG, - begin: Alignment.centerLeft, - end: Alignment.centerRight) - .createShader(Rect.fromLTRB( - 0, 0, bounds.width, bounds.height)); - }, - child: Text( - "78 BPM", - style: TextStyle( - color: - TColor.primaryColor1.withOpacity(0.7), - fontWeight: FontWeight.w700, - fontSize: 18), + TextField( + controller: bpmController, + readOnly: true, + style: TextStyle( + color: + TColor.primaryColor1.withOpacity(0.8), + fontWeight: FontWeight.w700, + fontSize: 18), + decoration: const InputDecoration( + border: InputBorder + .none, // Ajoutez cette ligne pour supprimer la bordure ), ), ], @@ -347,8 +285,9 @@ class _MobileHomeView extends State { getTooltipItems: (List lineBarsSpot) { return lineBarsSpot.map((lineBarSpot) { + bpmController.text = "${lineBarSpot.y} BPM"; return LineTooltipItem( - "il y a ${lineBarSpot.x.toInt()} minutes", + "Seconde ${lineBarSpot.x.toInt() / 10}", const TextStyle( color: Colors.white, fontSize: 10, @@ -360,12 +299,12 @@ class _MobileHomeView extends State { ), ), lineBarsData: lineBarsData, - minY: 0, - maxY: 130, - titlesData: FlTitlesData( + minY: 50, + maxY: 250, + titlesData: const FlTitlesData( show: false, ), - gridData: FlGridData(show: false), + gridData: const FlGridData(show: false), borderData: FlBorderData( show: true, border: Border.all( @@ -381,352 +320,17 @@ class _MobileHomeView extends State { SizedBox( height: media.width * 0.05, ), - Row( - children: [ - Expanded( - child: Container( - height: media.width * 0.95, - padding: const EdgeInsets.symmetric( - vertical: 25, horizontal: 20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(25), - boxShadow: const [ - BoxShadow(color: Colors.black12, blurRadius: 2) - ]), - child: Row( - children: [ - SimpleAnimationProgressBar( - height: media.width * 0.85, - width: media.width * 0.07, - backgroundColor: Colors.grey.shade100, - foregrondColor: Colors.purple, - ratio: 0.5, - direction: Axis.vertical, - curve: Curves.fastLinearToSlowEaseIn, - duration: const Duration(seconds: 3), - borderRadius: BorderRadius.circular(15), - gradientColor: LinearGradient( - colors: TColor.primaryG, - begin: Alignment.bottomCenter, - end: Alignment.topCenter), - ), - const SizedBox( - width: 10, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Graph 3", - style: TextStyle( - color: TColor.black, - fontSize: 12, - fontWeight: FontWeight.w700), - ), - ShaderMask( - blendMode: BlendMode.srcIn, - shaderCallback: (bounds) { - return LinearGradient( - colors: TColor.primaryG, - begin: Alignment.centerLeft, - end: Alignment.centerRight) - .createShader(Rect.fromLTRB( - 0, 0, bounds.width, bounds.height)); - }, - child: Text( - "ex : objectif", - style: TextStyle( - color: TColor.white.withOpacity(0.7), - fontWeight: FontWeight.w700, - fontSize: 14), - ), - ), - const SizedBox( - height: 10, - ), - Text( - "Mis à jour en temps réel", - style: TextStyle( - color: TColor.gray, - fontSize: 12, - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: waterArr.map((wObj) { - var isLast = wObj == waterArr.last; - return Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - Container( - margin: - const EdgeInsets.symmetric( - vertical: 4), - width: 10, - height: 10, - decoration: BoxDecoration( - color: TColor.secondaryColor1 - .withOpacity(0.5), - borderRadius: - BorderRadius.circular(5), - ), - ), - if (!isLast) - DottedDashedLine( - height: media.width * 0.078, - width: 0, - dashColor: TColor - .secondaryColor1 - .withOpacity(0.5), - axis: Axis.vertical) - ], - ), - const SizedBox( - width: 10, - ), - Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - wObj["title"].toString(), - style: TextStyle( - color: TColor.gray, - fontSize: 10, - ), - ), - ShaderMask( - blendMode: BlendMode.srcIn, - shaderCallback: (bounds) { - return LinearGradient( - colors: - TColor.secondaryG, - begin: Alignment - .centerLeft, - end: Alignment - .centerRight) - .createShader(Rect.fromLTRB( - 0, - 0, - bounds.width, - bounds.height)); - }, - child: Text( - wObj["subtitle"].toString(), - style: TextStyle( - color: TColor.white - .withOpacity(0.7), - fontSize: 12), - ), - ), - ], - ) - ], - ); - }).toList(), - ) - ], - )) - ], - ), - ), - ), - SizedBox( - width: media.width * 0.05, - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: double.maxFinite, - height: media.width * 0.45, - padding: const EdgeInsets.symmetric( - vertical: 25, horizontal: 20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(25), - boxShadow: const [ - BoxShadow(color: Colors.black12, blurRadius: 2) - ]), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Graph 4", - style: TextStyle( - color: TColor.black, - fontSize: 12, - fontWeight: FontWeight.w700), - ), - ShaderMask( - blendMode: BlendMode.srcIn, - shaderCallback: (bounds) { - return LinearGradient( - colors: TColor.primaryG, - begin: Alignment.centerLeft, - end: Alignment.centerRight) - .createShader(Rect.fromLTRB( - 0, 0, bounds.width, bounds.height)); - }, - child: Text( - "durée", - style: TextStyle( - color: TColor.white.withOpacity(0.7), - fontWeight: FontWeight.w700, - fontSize: 14), - ), - ), - const Spacer(), - Image.asset("assets/img/sleep_graph.png", - width: double.maxFinite, - height: 80, - fit: BoxFit.fitWidth) - ]), - ), - SizedBox( - height: media.width * 0.05, - ), - Container( - width: double.maxFinite, - height: media.width * 0.45, - padding: const EdgeInsets.symmetric( - vertical: 25, horizontal: 20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(25), - boxShadow: const [ - BoxShadow(color: Colors.black12, blurRadius: 2) - ]), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Calories", - style: TextStyle( - color: TColor.black, - fontSize: 12, - fontWeight: FontWeight.w700), - ), - ShaderMask( - blendMode: BlendMode.srcIn, - shaderCallback: (bounds) { - return LinearGradient( - colors: TColor.primaryG, - begin: Alignment.centerLeft, - end: Alignment.centerRight) - .createShader(Rect.fromLTRB( - 0, 0, bounds.width, bounds.height)); - }, - child: Text( - "760 kCal", - style: TextStyle( - color: TColor.white.withOpacity(0.7), - fontWeight: FontWeight.w700, - fontSize: 14), - ), - ), - const Spacer(), - Container( - alignment: Alignment.center, - child: SizedBox( - width: media.width * 0.2, - height: media.width * 0.2, - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: media.width * 0.15, - height: media.width * 0.15, - alignment: Alignment.center, - decoration: BoxDecoration( - gradient: LinearGradient( - colors: TColor.primaryG), - borderRadius: BorderRadius.circular( - media.width * 0.075), - ), - child: FittedBox( - child: Text( - "230kCal\nrestantes", - textAlign: TextAlign.center, - style: TextStyle( - color: TColor.white, - fontSize: 11), - ), - ), - ), - SimpleCircularProgressBar( - progressStrokeWidth: 10, - backStrokeWidth: 10, - progressColors: TColor.primaryG, - backColor: Colors.grey.shade100, - valueNotifier: ValueNotifier(50), - startAngle: -180, - ), - ], - ), - ), - ) - ]), - ), - ], - )) - ], - ), - SizedBox( - height: media.width * 0.1, - ), + const LigneContainerStats("1", "2", "3", "s", "s", "s"), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "graph 5", + "Rythme cardique et vitesse", style: TextStyle( color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700), ), - Container( - height: 30, - padding: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - gradient: LinearGradient(colors: TColor.primaryG), - borderRadius: BorderRadius.circular(15), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - items: ["Semaine", "Mois"] - .map((name) => DropdownMenuItem( - value: name, - child: Text( - name, - style: TextStyle( - color: TColor.gray, fontSize: 14), - ), - )) - .toList(), - onChanged: (value) {}, - icon: Icon(Icons.expand_more, color: TColor.white), - hint: Text( - "Semaine", - textAlign: TextAlign.center, - style: - TextStyle(color: TColor.white, fontSize: 12), - ), - ), - )), ], ), SizedBox( @@ -778,7 +382,7 @@ class _MobileHomeView extends State { List spotIndexes) { return spotIndexes.map((index) { return TouchedSpotIndicatorData( - FlLine( + const FlLine( color: Colors.transparent, ), FlDotData( @@ -801,7 +405,7 @@ class _MobileHomeView extends State { getTooltipItems: (List lineBarsSpot) { return lineBarsSpot.map((lineBarSpot) { return LineTooltipItem( - "il y a ${lineBarSpot.x.toInt()} minutes", + "Seconde ${lineBarSpot.x.toInt() / 10} ", const TextStyle( color: Colors.white, fontSize: 10, @@ -813,15 +417,13 @@ class _MobileHomeView extends State { ), ), lineBarsData: lineBarsData1, - minY: -0.5, + minY: 0, maxY: 110, titlesData: FlTitlesData( show: true, - leftTitles: AxisTitles(), - topTitles: AxisTitles(), - bottomTitles: AxisTitles( - sideTitles: bottomTitles, - ), + leftTitles: const AxisTitles(), + topTitles: const AxisTitles(), + bottomTitles: const AxisTitles(), rightTitles: AxisTitles( sideTitles: rightTitles, )), @@ -859,12 +461,6 @@ class _MobileHomeView extends State { ); } - void updateChartData(List newData) { - setState(() { - allSpots = newData; - }); - } - List showingSections() { return List.generate( 2, @@ -922,17 +518,9 @@ class _MobileHomeView extends State { ]), barWidth: 4, isStrokeCapRound: true, - dotData: FlDotData(show: false), + dotData: const FlDotData(show: false), belowBarData: BarAreaData(show: false), - spots: const [ - FlSpot(1, 35), - FlSpot(2, 70), - FlSpot(3, 40), - FlSpot(4, 80), - FlSpot(5, 25), - FlSpot(6, 70), - FlSpot(7, 35), - ], + spots: vitesseSecondes, ); LineChartBarData get lineChartBarData1_2 => LineChartBarData( @@ -943,19 +531,11 @@ class _MobileHomeView extends State { ]), barWidth: 2, isStrokeCapRound: true, - dotData: FlDotData(show: false), + dotData: const FlDotData(show: false), belowBarData: BarAreaData( show: false, ), - spots: const [ - FlSpot(1, 80), - FlSpot(2, 50), - FlSpot(3, 90), - FlSpot(4, 40), - FlSpot(5, 80), - FlSpot(6, 35), - FlSpot(7, 60), - ], + spots: bpmSecondes2, ); SideTitles get rightTitles => SideTitles( @@ -1000,7 +580,7 @@ class _MobileHomeView extends State { SideTitles get bottomTitles => SideTitles( showTitles: true, - reservedSize: 32, + reservedSize: 50, interval: 1, getTitlesWidget: bottomTitleWidgets, ); diff --git a/lib/view/ne_pas_supprimer/home_view.txt b/lib/view/ne_pas_supprimer/home_view.txt new file mode 100644 index 0000000..f89fb10 --- /dev/null +++ b/lib/view/ne_pas_supprimer/home_view.txt @@ -0,0 +1,1050 @@ +import 'package:dotted_dashed_line/dotted_dashed_line.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:simple_animation_progress_bar/simple_animation_progress_bar.dart'; +import 'package:simple_circular_progress_bar/simple_circular_progress_bar.dart'; +import 'package:smartfit_app_mobile/modele/user.dart'; +import 'package:smartfit_app_mobile/common/colo_extension.dart'; +import 'package:smartfit_app_mobile/common_widget/round_button.dart'; +import 'package:smartfit_app_mobile/view/home/activity_tracker.dart'; +import 'package:smartfit_app_mobile/view/home/notification_view.dart'; + +class MobileHomeView extends StatefulWidget { + const MobileHomeView({super.key}); + + @override + State createState() => _MobileHomeView(); +} + +class _MobileHomeView extends State { + List bpmSecondes = [FlSpot(0, 30)]; + List bpmSecondes2 = []; + double calories = 0.0; + List vitesseSecondes = [FlSpot(0, 30)]; + List altitudeSecondes = [FlSpot(0, 30)]; + + TextEditingController bpmController = TextEditingController(); + + void normaliserDeuxiemeElement(List liste) { + // Trouver le plus grand élément dans la liste + double maxElement = 0.0; + for (var spot in liste) { + if (spot.y > maxElement) { + maxElement = spot.y; + } + } + + // Calculer le facteur de normalisation + double normalisationFactor = maxElement != 0.0 ? 100 / maxElement : 1.0; + + // Mettre à jour tous les éléments de la liste + for (int i = 0; i < liste.length; i++) { + liste[i] = FlSpot(liste[i].x, liste[i].y * normalisationFactor); + } + } + + List lastWorkoutArr = [ + { + "name": "Full Body Workout", + "image": "assets/img/Workout1.png", + "kcal": "180", + "time": "20", + "progress": 0.3 + }, + { + "name": "Lower Body Workout", + "image": "assets/img/Workout2.png", + "kcal": "200", + "time": "30", + "progress": 0.4 + }, + { + "name": "Ab Workout", + "image": "assets/img/Workout3.png", + "kcal": "300", + "time": "40", + "progress": 0.7 + }, + ]; + List showingTooltipOnSpots = [0]; + + List waterArr = [ + {"title": "6am - 8am", "subtitle": "600ml"}, + {"title": "9am - 11am", "subtitle": "500ml"}, + {"title": "11am - 2pm", "subtitle": "1000ml"}, + {"title": "2pm - 4pm", "subtitle": "700ml"}, + {"title": "4pm - now", "subtitle": "900ml"}, + ]; + + @override + Widget build(BuildContext context) { + var media = MediaQuery.of(context).size; + + bpmSecondes = + Provider.of(context).listActivity[0].getHeartRateWithTime(); + vitesseSecondes = + Provider.of(context).listActivity[0].getSpeedWithTime(); + altitudeSecondes = + Provider.of(context).listActivity[0].getAltitudeWithTime(); + calories = double.parse( + Provider.of(context).listActivity[0].getTotalCalorie()); + + normaliserDeuxiemeElement(vitesseSecondes); + normaliserDeuxiemeElement(altitudeSecondes); + //bpmSecondes2 = List.from(bpmSecondes); + normaliserDeuxiemeElement(bpmSecondes); + + final lineBarsData = [ + LineChartBarData( + spots: bpmSecondes, + isCurved: false, + barWidth: 2, + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient(colors: [ + TColor.secondaryColor1.withOpacity(0.4), + TColor.secondaryColor2.withOpacity(0.1), + ], begin: Alignment.topCenter, end: Alignment.bottomCenter), + ), + dotData: FlDotData(show: false), + gradient: LinearGradient( + colors: TColor.secondaryG, + ), + ), + ]; + print("test5"); + + final tooltipsOnBar = lineBarsData[0]; + + return Scaffold( + backgroundColor: TColor.white, + body: SingleChildScrollView( + child: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Bienvenue,", + style: TextStyle(color: TColor.gray, fontSize: 12), + ), + Text( + "Benjelloun Othmane", + style: TextStyle( + color: TColor.black, + fontSize: 20, + fontWeight: FontWeight.w700), + ), + ], + ), + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const NotificationView(), + ), + ); + }, + icon: Image.asset( + "assets/img/notification_active.png", + width: 25, + height: 25, + fit: BoxFit.fitHeight, + )) + ], + ), + SizedBox( + height: media.width * 0.05, + ), + Container( + height: media.width * 0.4, + decoration: BoxDecoration( + gradient: LinearGradient(colors: TColor.primaryG), + borderRadius: BorderRadius.circular(media.width * 0.075)), + child: Stack(alignment: Alignment.center, children: [ + Image.asset( + "assets/img/bg_dots.png", + height: media.width * 0.4, + width: double.maxFinite, + fit: BoxFit.fitHeight, + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 25, horizontal: 25), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Graph 1", + style: TextStyle( + color: TColor.white, + fontSize: 14, + fontWeight: FontWeight.w700), + ), + Text( + "Sous titre 1", + style: TextStyle( + color: TColor.white.withOpacity(0.7), + fontSize: 12), + ), + SizedBox( + height: media.width * 0.05, + ), + SizedBox( + width: 120, + height: 35, + child: RoundButton( + title: "Voir plus", + type: RoundButtonType.bgSGradient, + fontSize: 12, + fontWeight: FontWeight.w400, + onPressed: () {})) + ], + ), + AspectRatio( + aspectRatio: 1, + child: PieChart( + PieChartData( + pieTouchData: PieTouchData( + touchCallback: + (FlTouchEvent event, pieTouchResponse) {}, + ), + startDegreeOffset: 250, + borderData: FlBorderData( + show: false, + ), + sectionsSpace: 1, + centerSpaceRadius: 0, + sections: showingSections(), + ), + ), + ), + ], + ), + ) + ]), + ), + SizedBox( + height: media.width * 0.05, + ), + Container( + padding: + const EdgeInsets.symmetric(vertical: 15, horizontal: 15), + decoration: BoxDecoration( + color: TColor.primaryColor2.withOpacity(0.3), + borderRadius: BorderRadius.circular(15), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Suivi d'activité", + style: TextStyle( + color: TColor.black, + fontSize: 14, + fontWeight: FontWeight.w700), + ), + SizedBox( + width: 70, + height: 25, + child: RoundButton( + title: "Voir", + type: RoundButtonType.bgGradient, + fontSize: 12, + fontWeight: FontWeight.w400, + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const ActivityTrackerView(), + ), + ); + }, + ), + ) + ], + ), + ), + SizedBox( + height: media.width * 0.05, + ), + Text( + "Status d'activité", + style: TextStyle( + color: TColor.black, + fontSize: 16, + fontWeight: FontWeight.w700), + ), + SizedBox( + height: media.width * 0.02, + ), + ClipRRect( + borderRadius: BorderRadius.circular(25), + child: Container( + height: media.width * 0.4, + width: double.maxFinite, + decoration: BoxDecoration( + color: TColor.primaryColor2.withOpacity(0.3), + borderRadius: BorderRadius.circular(25), + ), + child: Stack( + alignment: Alignment.topLeft, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + vertical: 20, horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Rythme cardiaque", + style: TextStyle( + color: TColor.black, + fontSize: 16, + fontWeight: FontWeight.w700), + ), + TextField( + controller: bpmController, + readOnly: true, + style: TextStyle( + color: + TColor.primaryColor1.withOpacity(0.8), + fontWeight: FontWeight.w700, + fontSize: 18), + decoration: InputDecoration( + border: InputBorder + .none, // Ajoutez cette ligne pour supprimer la bordure + ), + ), + ], + ), + ), + LineChart( + LineChartData( + showingTooltipIndicators: + showingTooltipOnSpots.map((index) { + return ShowingTooltipIndicators([ + LineBarSpot( + tooltipsOnBar, + lineBarsData.indexOf(tooltipsOnBar), + tooltipsOnBar.spots[index], + ), + ]); + }).toList(), + lineTouchData: LineTouchData( + enabled: true, + handleBuiltInTouches: false, + touchCallback: (FlTouchEvent event, + LineTouchResponse? response) { + if (response == null || + response.lineBarSpots == null) { + return; + } + if (event is FlTapUpEvent) { + final spotIndex = + response.lineBarSpots!.first.spotIndex; + showingTooltipOnSpots.clear(); + setState(() { + showingTooltipOnSpots.add(spotIndex); + }); + } + }, + mouseCursorResolver: (FlTouchEvent event, + LineTouchResponse? response) { + if (response == null || + response.lineBarSpots == null) { + return SystemMouseCursors.basic; + } + return SystemMouseCursors.click; + }, + getTouchedSpotIndicator: + (LineChartBarData barData, + List spotIndexes) { + return spotIndexes.map((index) { + return TouchedSpotIndicatorData( + FlLine( + color: TColor.secondaryColor1, + ), + FlDotData( + show: true, + getDotPainter: + (spot, percent, barData, index) => + FlDotCirclePainter( + radius: 3, + color: Colors.white, + strokeWidth: 3, + strokeColor: TColor.secondaryColor1, + ), + ), + ); + }).toList(); + }, + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: TColor.secondaryColor1, + tooltipRoundedRadius: 20, + getTooltipItems: + (List lineBarsSpot) { + return lineBarsSpot.map((lineBarSpot) { + bpmController.text = "${lineBarSpot.y} BPM"; + return LineTooltipItem( + "Seconde ${lineBarSpot.x.toInt() / 10}", + TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ); + }).toList(); + }, + ), + ), + lineBarsData: lineBarsData, + minY: 50, + maxY: 250, + titlesData: FlTitlesData( + show: false, + ), + gridData: FlGridData(show: false), + borderData: FlBorderData( + show: true, + border: Border.all( + color: Colors.transparent, + ), + ), + ), + ) + ], + ), + ), + ), + SizedBox( + height: media.width * 0.05, + ), + Row( + children: [ + Expanded( + child: Container( + height: media.width * 0.95, + padding: const EdgeInsets.symmetric( + vertical: 25, horizontal: 20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(25), + boxShadow: const [ + BoxShadow(color: Colors.black12, blurRadius: 2) + ]), + child: Row( + children: [ + SimpleAnimationProgressBar( + height: media.width * 0.85, + width: media.width * 0.07, + backgroundColor: Colors.grey.shade100, + foregrondColor: Colors.purple, + ratio: 0.5, + direction: Axis.vertical, + curve: Curves.fastLinearToSlowEaseIn, + duration: const Duration(seconds: 3), + borderRadius: BorderRadius.circular(15), + gradientColor: LinearGradient( + colors: TColor.primaryG, + begin: Alignment.bottomCenter, + end: Alignment.topCenter), + ), + const SizedBox( + width: 10, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Graph 3", + style: TextStyle( + color: TColor.black, + fontSize: 12, + fontWeight: FontWeight.w700), + ), + ShaderMask( + blendMode: BlendMode.srcIn, + shaderCallback: (bounds) { + return LinearGradient( + colors: TColor.primaryG, + begin: Alignment.centerLeft, + end: Alignment.centerRight) + .createShader(Rect.fromLTRB( + 0, 0, bounds.width, bounds.height)); + }, + child: Text( + "ex : objectif", + style: TextStyle( + color: TColor.white.withOpacity(0.7), + fontWeight: FontWeight.w700, + fontSize: 14), + ), + ), + const SizedBox( + height: 10, + ), + Text( + "Mis à jour en temps réel", + style: TextStyle( + color: TColor.gray, + fontSize: 12, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: waterArr.map((wObj) { + var isLast = wObj == waterArr.last; + return Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Container( + margin: + const EdgeInsets.symmetric( + vertical: 4), + width: 10, + height: 10, + decoration: BoxDecoration( + color: TColor.secondaryColor1 + .withOpacity(0.5), + borderRadius: + BorderRadius.circular(5), + ), + ), + if (!isLast) + DottedDashedLine( + height: media.width * 0.078, + width: 0, + dashColor: TColor + .secondaryColor1 + .withOpacity(0.5), + axis: Axis.vertical) + ], + ), + const SizedBox( + width: 10, + ), + Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + wObj["title"].toString(), + style: TextStyle( + color: TColor.gray, + fontSize: 10, + ), + ), + ShaderMask( + blendMode: BlendMode.srcIn, + shaderCallback: (bounds) { + return LinearGradient( + colors: + TColor.secondaryG, + begin: Alignment + .centerLeft, + end: Alignment + .centerRight) + .createShader(Rect.fromLTRB( + 0, + 0, + bounds.width, + bounds.height)); + }, + child: Text( + wObj["subtitle"].toString(), + style: TextStyle( + color: TColor.white + .withOpacity(0.7), + fontSize: 12), + ), + ), + ], + ) + ], + ); + }).toList(), + ) + ], + )) + ], + ), + ), + ), + SizedBox( + width: media.width * 0.05, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: double.maxFinite, + height: media.width * 0.45, + padding: const EdgeInsets.symmetric( + vertical: 25, horizontal: 20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(25), + boxShadow: const [ + BoxShadow(color: Colors.black12, blurRadius: 2) + ]), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Graph 4", + style: TextStyle( + color: TColor.black, + fontSize: 12, + fontWeight: FontWeight.w700), + ), + ShaderMask( + blendMode: BlendMode.srcIn, + shaderCallback: (bounds) { + return LinearGradient( + colors: TColor.primaryG, + begin: Alignment.centerLeft, + end: Alignment.centerRight) + .createShader(Rect.fromLTRB( + 0, 0, bounds.width, bounds.height)); + }, + child: Text( + "durée", + style: TextStyle( + color: TColor.white.withOpacity(0.7), + fontWeight: FontWeight.w700, + fontSize: 14), + ), + ), + const Spacer(), + Image.asset("assets/img/sleep_graph.png", + width: double.maxFinite, + height: 80, + fit: BoxFit.fitWidth) + ]), + ), + SizedBox( + height: media.width * 0.05, + ), + Container( + width: double.maxFinite, + height: media.width * 0.45, + padding: const EdgeInsets.symmetric( + vertical: 25, horizontal: 20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(25), + boxShadow: const [ + BoxShadow(color: Colors.black12, blurRadius: 2) + ]), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Calories", + style: TextStyle( + color: TColor.black, + fontSize: 12, + fontWeight: FontWeight.w700), + ), + ShaderMask( + blendMode: BlendMode.srcIn, + shaderCallback: (bounds) { + return LinearGradient( + colors: TColor.primaryG, + begin: Alignment.centerLeft, + end: Alignment.centerRight) + .createShader(Rect.fromLTRB( + 0, 0, bounds.width, bounds.height)); + }, + child: Text( + '${calories.toString()} kCal', + style: TextStyle( + color: TColor.white.withOpacity(0.7), + fontWeight: FontWeight.w700, + fontSize: 14), + ), + ), + const Spacer(), + Container( + alignment: Alignment.center, + child: SizedBox( + width: media.width * 0.2, + height: media.width * 0.2, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + width: media.width * 0.15, + height: media.width * 0.15, + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: TColor.primaryG), + borderRadius: BorderRadius.circular( + media.width * 0.075), + ), + child: FittedBox( + child: Text( + '${200 - calories.toInt()} kCal\n restantes', + textAlign: TextAlign.center, + style: TextStyle( + color: TColor.white, + fontSize: 11), + ), + ), + ), + SimpleCircularProgressBar( + progressStrokeWidth: 10, + backStrokeWidth: 10, + progressColors: TColor.primaryG, + backColor: Colors.grey.shade100, + valueNotifier: ValueNotifier( + calories / 200 * 100), + startAngle: -180, + ), + ], + ), + ), + ) + ]), + ), + ], + )) + ], + ), + SizedBox( + height: media.width * 0.1, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Rythme cardique et vitesse", + style: TextStyle( + color: TColor.black, + fontSize: 16, + fontWeight: FontWeight.w700), + ), + ], + ), + SizedBox( + height: media.width * 0.05, + ), + Container( + padding: const EdgeInsets.only(left: 15), + height: media.width * 0.5, + width: double.maxFinite, + child: LineChart( + LineChartData( + showingTooltipIndicators: + showingTooltipOnSpots.map((index) { + return ShowingTooltipIndicators([ + LineBarSpot( + tooltipsOnBar, + lineBarsData.indexOf(tooltipsOnBar), + tooltipsOnBar.spots[index], + ), + ]); + }).toList(), + lineTouchData: LineTouchData( + enabled: true, + handleBuiltInTouches: false, + touchCallback: (FlTouchEvent event, + LineTouchResponse? response) { + if (response == null || + response.lineBarSpots == null) { + return; + } + if (event is FlTapUpEvent) { + final spotIndex = + response.lineBarSpots!.first.spotIndex; + showingTooltipOnSpots.clear(); + setState(() { + showingTooltipOnSpots.add(spotIndex); + }); + } + }, + mouseCursorResolver: (FlTouchEvent event, + LineTouchResponse? response) { + if (response == null || + response.lineBarSpots == null) { + return SystemMouseCursors.basic; + } + return SystemMouseCursors.click; + }, + getTouchedSpotIndicator: (LineChartBarData barData, + List spotIndexes) { + return spotIndexes.map((index) { + return TouchedSpotIndicatorData( + FlLine( + color: Colors.transparent, + ), + FlDotData( + show: true, + getDotPainter: + (spot, percent, barData, index) => + FlDotCirclePainter( + radius: 3, + color: Colors.white, + strokeWidth: 3, + strokeColor: TColor.secondaryColor1, + ), + ), + ); + }).toList(); + }, + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: TColor.secondaryColor1, + tooltipRoundedRadius: 20, + getTooltipItems: (List lineBarsSpot) { + return lineBarsSpot.map((lineBarSpot) { + return LineTooltipItem( + "Seconde ${lineBarSpot.x.toInt() / 10} ", + const TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ); + }).toList(); + }, + ), + ), + lineBarsData: lineBarsData1, + minY: 0, + maxY: 110, + titlesData: FlTitlesData( + show: true, + leftTitles: AxisTitles(), + topTitles: AxisTitles(), + bottomTitles: AxisTitles(), + rightTitles: AxisTitles( + sideTitles: rightTitles, + )), + gridData: FlGridData( + show: true, + drawHorizontalLine: true, + horizontalInterval: 25, + drawVerticalLine: false, + getDrawingHorizontalLine: (value) { + return FlLine( + color: TColor.gray.withOpacity(0.15), + strokeWidth: 2, + ); + }, + ), + borderData: FlBorderData( + show: true, + border: Border.all( + color: Colors.transparent, + ), + ), + ), + )), + SizedBox( + height: media.width * 0.05, + ), + SizedBox( + height: media.width * 0.1, + ), + ], + ), + ), + ), + ), + ); + } + + List showingSections() { + return List.generate( + 2, + (i) { + var color0 = TColor.secondaryColor1; + + switch (i) { + case 0: + return PieChartSectionData( + color: color0, + value: 33, + title: '', + radius: 55, + titlePositionPercentageOffset: 0.55, + badgeWidget: const Text( + "20,1", + style: TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w700), + )); + case 1: + return PieChartSectionData( + color: Colors.white, + value: 75, + title: '', + radius: 45, + titlePositionPercentageOffset: 0.55, + ); + + default: + throw Error(); + } + }, + ); + } + + LineTouchData get lineTouchData1 => LineTouchData( + handleBuiltInTouches: true, + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.blueGrey.withOpacity(0.8), + ), + ); + + List get lineBarsData1 => [ + lineChartBarData1_1, + lineChartBarData1_2, + ]; + + LineChartBarData get lineChartBarData1_1 => LineChartBarData( + isCurved: true, + gradient: LinearGradient(colors: [ + TColor.primaryColor2.withOpacity(0.5), + TColor.primaryColor1.withOpacity(0.5), + ]), + barWidth: 4, + isStrokeCapRound: true, + dotData: FlDotData(show: false), + belowBarData: BarAreaData(show: false), + spots: vitesseSecondes, + ); + + LineChartBarData get lineChartBarData1_2 => LineChartBarData( + isCurved: true, + gradient: LinearGradient(colors: [ + TColor.secondaryColor2.withOpacity(0.5), + TColor.secondaryColor1.withOpacity(0.5), + ]), + barWidth: 2, + isStrokeCapRound: true, + dotData: FlDotData(show: false), + belowBarData: BarAreaData( + show: false, + ), + spots: bpmSecondes2, + ); + + SideTitles get rightTitles => SideTitles( + getTitlesWidget: rightTitleWidgets, + showTitles: true, + interval: 20, + reservedSize: 40, + ); + + Widget rightTitleWidgets(double value, TitleMeta meta) { + String text; + switch (value.toInt()) { + case 0: + text = '0%'; + break; + case 20: + text = '20%'; + break; + case 40: + text = '40%'; + break; + case 60: + text = '60%'; + break; + case 80: + text = '80%'; + break; + case 100: + text = '100%'; + break; + default: + return Container(); + } + + return Text(text, + style: TextStyle( + color: TColor.gray, + fontSize: 12, + ), + textAlign: TextAlign.center); + } + + SideTitles get bottomTitles => SideTitles( + showTitles: true, + reservedSize: 50, + interval: 1, + getTitlesWidget: bottomTitleWidgets, + ); + + Widget bottomTitleWidgets(double value, TitleMeta meta) { + var style = TextStyle( + color: TColor.gray, + fontSize: 12, + ); + Widget text; + switch (value.toInt()) { + case 1: + text = Text('Dim', style: style); + break; + case 2: + text = Text('Lun', style: style); + break; + case 3: + text = Text('Mar', style: style); + break; + case 4: + text = Text('Mer', style: style); + break; + case 5: + text = Text('Jeu', style: style); + break; + case 6: + text = Text('Ven', style: style); + break; + case 7: + text = Text('Sam', style: style); + break; + default: + text = Text('', style: style); + break; + } + + return SideTitleWidget( + axisSide: meta.axisSide, + space: 10, + child: text, + ); + } +}