💥 offline mode (enfin)

pull/4/head
remrem 1 year ago
commit 769139fa03

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@ -0,0 +1,19 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.48445 22.0001H1.00973C0.870493 22.0005 0.732683 21.9735 0.605006 21.9207C0.47733 21.8679 0.362566 21.7905 0.26797 21.6934C0.173374 21.5964 0.101003 21.4817 0.0554335 21.3566C0.00986404 21.2316 -0.0079129 21.0989 0.00322648 20.9671L0.481314 15.3044H7.47145C9.48445 22.0384 9.09695 20.6992 9.48445 22.0001Z" fill="#E2E2E2"/>
<path d="M13.0072 3.82618V12.4349H0.717834L1.35696 4.70618C1.37725 4.46598 1.49218 4.24191 1.67878 4.07876C1.86538 3.91561 2.1099 3.8254 2.36346 3.82618H2.9422C2.9422 5.94009 6.9682 10.5218 6.9682 10.5218C6.9682 10.5218 10.9942 5.94009 10.9942 3.82618H13.0072Z" fill="#E2E2E2"/>
<path d="M21.2706 12.4349H16.0267V3.82618H19.625C19.8785 3.8254 20.123 3.91561 20.3097 4.07876C20.4963 4.24191 20.6112 4.46598 20.6315 4.70618L21.2706 12.4349Z" fill="#E2E2E2"/>
<path d="M21.9852 21.0436C21.9852 21.2973 21.8792 21.5406 21.6904 21.7199C21.5016 21.8993 21.2456 22.0001 20.9787 22.0001H12.504L10.491 15.3044H21.5071C22.1311 22.7844 21.9852 20.5892 21.9852 21.0436Z" fill="#E2E2E2"/>
<path d="M9.48445 22.0001H1.00973C0.870493 22.0005 0.732683 21.9735 0.605006 21.9207C0.47733 21.8679 0.362566 21.7905 0.26797 21.6934C0.173374 21.5964 0.101003 21.4817 0.0554335 21.3566C0.00986404 21.2316 -0.0079129 21.0989 0.00322648 20.9671L0.481314 15.3044H7.47145C9.48445 22.0384 9.09695 20.6992 9.48445 22.0001Z" fill="#E2E2E2"/>
<path d="M13.0072 3.82618V12.4349H0.717834L1.35696 4.70618C1.37725 4.46598 1.49218 4.24191 1.67878 4.07876C1.86538 3.91561 2.1099 3.8254 2.36346 3.82618H2.9422C2.9422 5.94009 6.9682 10.5218 6.9682 10.5218C6.9682 10.5218 10.9942 5.94009 10.9942 3.82618H13.0072Z" fill="#E2E2E2"/>
<path d="M21.2706 12.4349H16.0267V3.82618H19.625C19.8785 3.8254 20.123 3.91561 20.3097 4.07876C20.4963 4.24191 20.6112 4.46598 20.6315 4.70618L21.2706 12.4349Z" fill="#E2E2E2"/>
<path d="M21.9852 21.0436C21.9852 21.2973 21.8792 21.5406 21.6904 21.7199C21.5016 21.8993 21.2456 22.0001 20.9787 22.0001H12.504L10.491 15.3044H21.5071C22.1311 22.7844 21.9852 20.5892 21.9852 21.0436Z" fill="#E2E2E2"/>
<path d="M12.504 22.0001H9.48446L7.47146 15.3044H0.481323L0.717851 12.4349H13.0072V3.82617H16.0267V12.4349H21.2706L21.5071 15.3044H10.491C12.504 22.0383 12.1165 20.6992 12.504 22.0001Z" fill="white"/>
<path d="M10.491 15.3044L12.2171 21.0436H9.19763L7.47148 15.3044H1.93573C2.03638 14.0992 1.98605 14.7353 2.17226 12.4349H13.0072V3.82617H16.0267V12.4349H21.2706L21.5071 15.3044H10.491Z" fill="white"/>
<path d="M13.0072 3.82617V12.4349H2.14709C2.25278 11.1675 2.14709 12.2531 2.68054 5.98791C3.63073 7.58863 4.72879 9.10591 5.96173 10.5218C5.96173 10.5218 6.158 10.297 6.46498 9.924C6.77196 10.297 6.96823 10.5218 6.96823 10.5218C6.96823 10.5218 10.9942 5.94008 10.9942 3.82617H13.0072Z" fill="#BBBBBB"/>
<path d="M9.19762 21.0436H2.51949C2.38026 21.044 2.24245 21.017 2.11477 20.9642C1.9871 20.9114 1.87233 20.834 1.77774 20.7369C1.68314 20.6398 1.61077 20.5251 1.5652 20.4001C1.51963 20.2751 1.50185 20.1424 1.51299 20.0105L1.93572 15.3044H7.47147L9.19762 21.0436Z" fill="#BBBBBB"/>
<path d="M21.9852 21.0436H12.2171L10.491 15.3044H21.5071C22.1311 22.7844 21.9852 20.5892 21.9852 21.0436Z" fill="#BBBBBB"/>
<path d="M21.2706 12.4349H16.0267V3.82618H19.625C19.8785 3.8254 20.123 3.91561 20.3097 4.07876C20.4963 4.24191 20.6112 4.46598 20.6315 4.70618L21.2706 12.4349Z" fill="#BBBBBB"/>
<path d="M10.9942 3.82609C10.9942 5.59087 8.12064 9.20174 6.9682 10.5217C6.9682 10.5217 2.9422 5.94 2.9422 3.82609C2.9422 2.81134 3.36637 1.83816 4.12139 1.12063C4.87641 0.403104 5.90044 0 6.9682 0C8.03596 0 9.05999 0.403104 9.81501 1.12063C10.57 1.83816 10.9942 2.81134 10.9942 3.82609Z" fill="#7B6F72"/>
<path d="M10.9942 3.82615C10.9942 5.29441 9.04661 7.95832 7.86397 9.44093C7.22987 8.69962 3.94869 4.78267 3.94869 2.86962C3.94638 2.08883 4.19963 1.32668 4.67336 0.688755C5.27683 0.290897 5.98333 0.0575021 6.71636 0.0138413C7.44938 -0.0298194 8.18101 0.117917 8.83203 0.441056C9.48305 0.764194 10.0287 1.25042 10.4098 1.84709C10.7909 2.44377 10.993 3.12815 10.9942 3.82615Z" fill="#ADA4A5"/>
<path d="M6.96825 5.26092C7.80206 5.26092 8.47799 4.61855 8.47799 3.82614C8.47799 3.03373 7.80206 2.39136 6.96825 2.39136C6.13443 2.39136 5.4585 3.03373 5.4585 3.82614C5.4585 4.61855 6.13443 5.26092 6.96825 5.26092Z" fill="#7B6F72"/>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,81 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.48445 22.0001H1.00973C0.870493 22.0005 0.732683 21.9735 0.605006 21.9207C0.47733 21.8679 0.362566 21.7905 0.26797 21.6934C0.173374 21.5964 0.101003 21.4817 0.0554335 21.3566C0.00986404 21.2316 -0.0079129 21.0989 0.00322648 20.9671L0.481314 15.3044H7.47145C9.48445 22.0384 9.09695 20.6992 9.48445 22.0001Z" fill="url(#paint0_linear_1054_2509)"/>
<path d="M13.0072 3.82618V12.4349H0.717834L1.35696 4.70618C1.37725 4.46598 1.49218 4.24191 1.67878 4.07876C1.86538 3.91561 2.1099 3.8254 2.36346 3.82618H2.9422C2.9422 5.94009 6.9682 10.5218 6.9682 10.5218C6.9682 10.5218 10.9942 5.94009 10.9942 3.82618H13.0072Z" fill="url(#paint1_linear_1054_2509)"/>
<path d="M21.2706 12.4349H16.0267V3.82618H19.625C19.8785 3.8254 20.123 3.91561 20.3097 4.07876C20.4963 4.24191 20.6112 4.46598 20.6315 4.70618L21.2706 12.4349Z" fill="url(#paint2_linear_1054_2509)"/>
<path d="M21.9852 21.0436C21.9852 21.2973 21.8792 21.5406 21.6904 21.7199C21.5016 21.8993 21.2456 22.0001 20.9787 22.0001H12.504L10.491 15.3044H21.5071C22.1311 22.7844 21.9852 20.5892 21.9852 21.0436Z" fill="url(#paint3_linear_1054_2509)"/>
<path d="M9.48445 22.0001H1.00973C0.870493 22.0005 0.732683 21.9735 0.605006 21.9207C0.47733 21.8679 0.362566 21.7905 0.26797 21.6934C0.173374 21.5964 0.101003 21.4817 0.0554335 21.3566C0.00986404 21.2316 -0.0079129 21.0989 0.00322648 20.9671L0.481314 15.3044H7.47145C9.48445 22.0384 9.09695 20.6992 9.48445 22.0001Z" fill="url(#paint4_linear_1054_2509)"/>
<path d="M13.0072 3.82618V12.4349H0.717834L1.35696 4.70618C1.37725 4.46598 1.49218 4.24191 1.67878 4.07876C1.86538 3.91561 2.1099 3.8254 2.36346 3.82618H2.9422C2.9422 5.94009 6.9682 10.5218 6.9682 10.5218C6.9682 10.5218 10.9942 5.94009 10.9942 3.82618H13.0072Z" fill="url(#paint5_linear_1054_2509)"/>
<path d="M21.2706 12.4349H16.0267V3.82618H19.625C19.8785 3.8254 20.123 3.91561 20.3097 4.07876C20.4963 4.24191 20.6112 4.46598 20.6315 4.70618L21.2706 12.4349Z" fill="url(#paint6_linear_1054_2509)"/>
<path d="M21.9852 21.0436C21.9852 21.2973 21.8792 21.5406 21.6904 21.7199C21.5016 21.8993 21.2456 22.0001 20.9787 22.0001H12.504L10.491 15.3044H21.5071C22.1311 22.7844 21.9852 20.5892 21.9852 21.0436Z" fill="url(#paint7_linear_1054_2509)"/>
<path d="M12.504 22.0001H9.48446L7.47146 15.3044H0.481323L0.717851 12.4349H13.0072V3.82617H16.0267V12.4349H21.2706L21.5071 15.3044H10.491C12.504 22.0383 12.1165 20.6992 12.504 22.0001Z" fill="white"/>
<path d="M10.491 15.3044L12.2171 21.0436H9.19763L7.47148 15.3044H1.93573C2.03638 14.0992 1.98605 14.7353 2.17226 12.4349H13.0072V3.82617H16.0267V12.4349H21.2706L21.5071 15.3044H10.491Z" fill="white"/>
<path d="M13.0072 3.82617V12.4349H2.14709C2.25278 11.1675 2.14709 12.2531 2.68054 5.98791C3.63073 7.58863 4.72879 9.10591 5.96173 10.5218C5.96173 10.5218 6.158 10.297 6.46498 9.924C6.77196 10.297 6.96823 10.5218 6.96823 10.5218C6.96823 10.5218 10.9942 5.94008 10.9942 3.82617H13.0072Z" fill="url(#paint8_linear_1054_2509)"/>
<path d="M9.19762 21.0436H2.51949C2.38026 21.044 2.24245 21.017 2.11477 20.9642C1.9871 20.9114 1.87233 20.834 1.77774 20.7369C1.68314 20.6398 1.61077 20.5251 1.5652 20.4001C1.51963 20.2751 1.50185 20.1424 1.51299 20.0105L1.93572 15.3044H7.47147L9.19762 21.0436Z" fill="url(#paint9_linear_1054_2509)"/>
<path d="M21.9852 21.0436H12.2171L10.491 15.3044H21.5071C22.1311 22.7844 21.9852 20.5892 21.9852 21.0436Z" fill="url(#paint10_linear_1054_2509)"/>
<path d="M21.2706 12.4349H16.0267V3.82618H19.625C19.8785 3.8254 20.123 3.91561 20.3097 4.07876C20.4963 4.24191 20.6112 4.46598 20.6315 4.70618L21.2706 12.4349Z" fill="url(#paint11_linear_1054_2509)"/>
<path d="M10.9942 3.82609C10.9942 5.59087 8.12064 9.20174 6.9682 10.5217C6.9682 10.5217 2.9422 5.94 2.9422 3.82609C2.9422 2.81134 3.36637 1.83816 4.12139 1.12063C4.87641 0.403104 5.90044 0 6.9682 0C8.03596 0 9.05999 0.403104 9.81501 1.12063C10.57 1.83816 10.9942 2.81134 10.9942 3.82609Z" fill="url(#paint12_linear_1054_2509)"/>
<path d="M10.9942 3.82615C10.9942 5.29441 9.04661 7.95832 7.86397 9.44093C7.22987 8.69962 3.94869 4.78267 3.94869 2.86962C3.94638 2.08883 4.19963 1.32668 4.67336 0.688755C5.27683 0.290897 5.98333 0.0575021 6.71636 0.0138413C7.44938 -0.0298194 8.18101 0.117917 8.83203 0.441056C9.48305 0.764194 10.0287 1.25042 10.4098 1.84709C10.7909 2.44377 10.993 3.12815 10.9942 3.82615Z" fill="url(#paint13_linear_1054_2509)"/>
<path d="M6.96825 5.26092C7.80206 5.26092 8.47799 4.61855 8.47799 3.82614C8.47799 3.03373 7.80206 2.39136 6.96825 2.39136C6.13443 2.39136 5.4585 3.03373 5.4585 3.82614C5.4585 4.61855 6.13443 5.26092 6.96825 5.26092Z" fill="url(#paint14_linear_1054_2509)"/>
<defs>
<linearGradient id="paint0_linear_1054_2509" x1="4.74223" y1="9.73951" x2="4.74223" y2="19.3617" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint1_linear_1054_2509" x1="6.86251" y1="-3.32874" x2="6.86251" y2="9.0427" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint2_linear_1054_2509" x1="18.6487" y1="-3.32874" x2="18.6487" y2="9.0427" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint3_linear_1054_2509" x1="16.2455" y1="9.73952" x2="16.2455" y2="19.3617" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint4_linear_1054_2509" x1="4.74223" y1="9.73951" x2="4.74223" y2="19.3617" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint5_linear_1054_2509" x1="6.86251" y1="-3.32874" x2="6.86251" y2="9.0427" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint6_linear_1054_2509" x1="18.6487" y1="-3.32874" x2="18.6487" y2="9.0427" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint7_linear_1054_2509" x1="16.2455" y1="9.73952" x2="16.2455" y2="19.3617" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#B4C0FE"/>
</linearGradient>
<linearGradient id="paint8_linear_1054_2509" x1="13.0072" y1="12.4349" x2="-1.41631" y2="11.0269" gradientUnits="userSpaceOnUse">
<stop stop-color="#6131AD"/>
<stop offset="1" stop-color="#D4B9FF"/>
</linearGradient>
<linearGradient id="paint9_linear_1054_2509" x1="9.19762" y1="21.0436" x2="-1.00048" y2="19.9865" gradientUnits="userSpaceOnUse">
<stop stop-color="#6131AD"/>
<stop offset="1" stop-color="#D4B9FF"/>
</linearGradient>
<linearGradient id="paint10_linear_1054_2509" x1="22" y1="21.0436" x2="6.93183" y2="18.7053" gradientUnits="userSpaceOnUse">
<stop stop-color="#6131AD"/>
<stop offset="1" stop-color="#D4B9FF"/>
</linearGradient>
<linearGradient id="paint11_linear_1054_2509" x1="21.2706" y1="12.4349" x2="14.2553" y2="12.1042" gradientUnits="userSpaceOnUse">
<stop stop-color="#6131AD"/>
<stop offset="1" stop-color="#D4B9FF"/>
</linearGradient>
<linearGradient id="paint12_linear_1054_2509" x1="10.9942" y1="10.5217" x2="0.236016" y2="9.88466" gradientUnits="userSpaceOnUse">
<stop stop-color="#6131AD"/>
<stop offset="1" stop-color="#D4B9FF"/>
</linearGradient>
<linearGradient id="paint13_linear_1054_2509" x1="15.5794" y1="4.72364" x2="4.80068" y2="4.34559" gradientUnits="userSpaceOnUse">
<stop stop-color="#C58BF2"/>
<stop offset="1" stop-color="#92A3FD"/>
</linearGradient>
<linearGradient id="paint14_linear_1054_2509" x1="8.478" y1="5.26092" x2="4.45619" y2="4.93345" gradientUnits="userSpaceOnUse">
<stop stop-color="#6131AD"/>
<stop offset="1" stop-color="#D4B9FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

@ -1,7 +1,11 @@
import 'package:smartfit_app_mobile/modele/activity_saver.dart';
import 'package:smartfit_app_mobile/modele/helper.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common_widget/container/workout_row.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart'; import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row_generic.dart';
import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row_walking.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart'; import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
@ -24,73 +28,112 @@ class _ListActivityWidget extends State<ListActivityWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Material( Future<void> onClick(ActivityOfUser activityObj) async {
color: Colors.transparent, if (!Provider.of<User>(context, listen: false)
child: ListView.builder( .managerSelectedActivity
padding: EdgeInsets.zero, .fileNotSelected(activityObj.fileUuid)) {
physics: const NeverScrollableScrollPhysics(), Provider.of<User>(context, listen: false)
shrinkWrap: true, .managerSelectedActivity
itemCount: Provider.of<User>(context, listen: true).listActivity.length, .removeSelectedActivity(activityObj.fileUuid);
itemBuilder: (context, index) { setState(() {});
ActivityOfUser activityObj = return;
Provider.of<User>(context, listen: true).listActivity[index]; }
Map<String, dynamic> activityMap;
// -- Si categorie == marche Tuple2<bool, String> result =
if (activityObj.category == managerFile.marche) { await _utile.getContentActivity(context, activityObj, infoManager);
activityMap = activityObj.toMapWalking(); if (!result.item1) {
} else { return;
// -- Default -- // }
activityMap = activityObj.toMapGeneric();
}
return InkWell( // TODO: Hein?
onTap: () {}, Provider.of<User>(context, listen: false).removeActivity(activityObj);
child: WorkoutRow( Provider.of<User>(context, listen: false).insertActivity(0, activityObj);
wObj: activityMap, }
onDelete: () async {
if (await api.deleteFile(
Provider.of<User>(context, listen: false).token,
activityObj.fileUuid,
infoManager)) {
if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity
.fileNotSelected(activityObj.fileUuid)) {
Provider.of<User>(context, listen: false)
.managerSelectedActivity
.removeSelectedActivity(activityObj.fileUuid);
}
Provider.of<User>(context, listen: false)
.removeActivity(activityObj);
}
},
onClick: () async {
if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity
.fileNotSelected(activityObj.fileUuid)) {
Provider.of<User>(context, listen: false)
.managerSelectedActivity
.removeSelectedActivity(activityObj.fileUuid);
setState(() {});
return;
}
Tuple2<bool, String> result = // TODO: Understand :(
await _utile.getContentActivity(context, activityObj); Future<void> onDelete(ActivityOfUser activityObj) async {
if (!result.item1) { if (await api.deleteFile(Provider.of<User>(context, listen: false).token,
return; activityObj.fileUuid, infoManager)) {
} if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity
.fileNotSelected(activityObj.fileUuid)) {
Provider.of<User>(context, listen: false)
.managerSelectedActivity
.removeSelectedActivity(activityObj.fileUuid);
}
if (!Helper.isPlatformWeb()) {
ActivitySaver actSaver = await ActivitySaver.create();
actSaver.deleteActivity(activityObj.fileUuid);
localDB.removeActivity(activityObj.fileUuid);
}
Provider.of<User>(context, listen: false).removeActivity(activityObj);
}
}
Provider.of<User>(context, listen: false) bool isSelected(ActivityOfUser activityObj) {
.removeActivity(activityObj); return !Provider.of<User>(context)
Provider.of<User>(context, listen: false) .managerSelectedActivity
.insertActivity(0, activityObj); .fileNotSelected(activityObj.fileUuid);
}, }
isSelected: !Provider.of<User>(context)
.managerSelectedActivity return Material(
.fileNotSelected(activityObj.fileUuid), color: Colors.transparent,
), child: Column(
); children: [
}, Visibility(
visible: infoManager.isVisible,
child: Text(infoManager.message,
style: TextStyle(color: infoManager.messageColor))),
ListView.builder(
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount:
Provider.of<User>(context, listen: true).listActivity.length,
itemBuilder: (context, index) {
ActivityOfUser activityObj =
Provider.of<User>(context, listen: true).listActivity[index];
Map<String, dynamic> activityMap;
// -- Si categorie == marche
if (activityObj.category == managerFile.marche) {
activityMap = activityObj.toMapWalking();
return InkWell(
onTap: () {},
child: WorkoutRowWalking(
wObj: activityMap,
onDelete: () async {
await onDelete(activityObj);
setState(() {});
},
onClick: () async {
await onClick(activityObj);
setState(() {});
},
isSelected: isSelected(activityObj),
),
);
} else {
// -- Default -- //
activityMap = activityObj.toMapGeneric();
return InkWell(
onTap: () {},
child: WorkoutRowGeneric(
wObj: activityMap,
onDelete: () async {
await onDelete(activityObj);
setState(() {});
},
onClick: () async {
await onClick(activityObj);
setState(() {});
},
isSelected: isSelected(activityObj),
),
);
}
},
),
],
), ),
); );
} }

@ -45,17 +45,7 @@ class ProfileEntete extends StatelessWidget {
], ],
), ),
), ),
SizedBox(
width: 70,
height: 25,
child: RoundButton(
title: "Editer",
type: RoundButtonType.bgGradient,
fontSize: 12,
fontWeight: FontWeight.w400,
onPressed: () {},
),
)
], ],
); );
} }

@ -21,7 +21,7 @@ class ProfileInfoUser extends StatelessWidget {
), ),
Expanded( Expanded(
child: TitleSubtitleCell( child: TitleSubtitleCell(
title: context.watch<User>().getTotalTimeAllActivity().toString(), title: context.watch<User>().getTotalTimeAllActivity().toStringAsFixed(2),
subtitle: "Temps en activité", subtitle: "Temps en activité",
), ),
), ),
@ -31,7 +31,7 @@ class ProfileInfoUser extends StatelessWidget {
Expanded( Expanded(
child: TitleSubtitleCell( child: TitleSubtitleCell(
title: title:
"${context.watch<User>().getTotalDenivelePositif().toString()} + m", "${context.watch<User>().getTotalDenivelePositifAllActivity().toStringAsFixed(2)} + m",
subtitle: "Total dénivelé positif", subtitle: "Total dénivelé positif",
), ),
), ),
@ -41,7 +41,7 @@ class ProfileInfoUser extends StatelessWidget {
Expanded( Expanded(
child: TitleSubtitleCell( child: TitleSubtitleCell(
title: title:
"${context.watch<User>().getTotalDeniveleNegatif().toString()} - m", "${context.watch<User>().getTotalDeniveleNegatifAllActivity().toStringAsFixed(2)} - m",
subtitle: "Total dénivelé négatif", subtitle: "Total dénivelé négatif",
), ),
), ),

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/main.dart';
class ProfileSwitch extends StatefulWidget {
final String title;
final String description;
final String iconFilename;
const ProfileSwitch(this.title, this.description, this.iconFilename,
{super.key});
@override
State<ProfileSwitch> createState() => _ProfileSwitchState();
}
class _ProfileSwitchState extends State<ProfileSwitch> {
bool switchValue = localDB.getSaveLocally();
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
decoration: BoxDecoration(
color: TColor.white,
borderRadius: BorderRadius.circular(15),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 2)]),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
widget.title,
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
SizedBox(
height: 30,
child:
Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
Image.asset("assets/img/${widget.iconFilename}",
height: 28, width: 28, fit: BoxFit.contain),
const SizedBox(
width: 15,
),
Expanded(
child: Text(
widget.description,
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
),
Switch(
value: switchValue,
activeColor: Colors.orange,
onChanged: (bool value) {
setState(() {
switchValue = value;
localDB.setSaveLocally(switchValue);
});
}),
]))
]));
}
}

@ -0,0 +1,118 @@
import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/convertisseur.dart';
class WorkoutRowGeneric extends StatelessWidget {
final Map wObj;
final bool isSelected;
final VoidCallback onDelete;
final VoidCallback onClick;
const WorkoutRowGeneric({
Key? key,
required this.wObj,
required this.onDelete,
required this.onClick,
required this.isSelected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onClick,
child: Container(
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 2),
decoration: BoxDecoration(
border: Border.all(
color: isSelected
? const Color.fromARGB(255, 144, 252, 148)
: Colors.transparent,
width: 2.0,
),
borderRadius: BorderRadius.circular(10),
),
child: Material(
color: isSelected
? const Color.fromARGB(255, 240, 255, 240)
: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(10), // Utiliser le même borderRadius
splashColor: const Color.fromARGB(255, 42, 94, 44)
.withOpacity(0.3), // Couleur du fond au survol
onTap: onClick,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SvgPicture.asset(
wObj["image"].toString(),
width: 60,
height: 60,
fit: BoxFit.cover,
),
),
const SizedBox(width: 15),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Type : ${wObj["categorie"].toString()}",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
Text(
"Date : ${wObj["date"].toString()}",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
Text(
"Temps : ${Convertisseur.secondeIntoMinute(wObj["time"]).toStringAsFixed(2)} m",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
)
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IconButton(
onPressed: onClick,
icon: Image.asset(
"assets/img/next_icon.png",
width: 30,
height: 30,
fit: BoxFit.contain,
),
),
IconButton(
onPressed: onDelete,
icon: Image.asset(
"assets/img/corbeille.png",
width: 30,
height: 30,
fit: BoxFit.contain,
),
),
],
),
],
),
),
),
),
),
);
}
}

@ -1,14 +1,15 @@
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/convertisseur.dart';
class WorkoutRow extends StatelessWidget { class WorkoutRowWalking extends StatelessWidget {
final Map wObj; final Map wObj;
final bool isSelected; final bool isSelected;
final VoidCallback onDelete; final VoidCallback onDelete;
final VoidCallback onClick; final VoidCallback onClick;
const WorkoutRow({ const WorkoutRowWalking({
Key? key, Key? key,
required this.wObj, required this.wObj,
required this.onDelete, required this.onDelete,
@ -74,14 +75,14 @@ class WorkoutRow extends StatelessWidget {
), ),
), ),
Text( Text(
"Temps : ${wObj["time"].toString()}", "Temps : ${Convertisseur.secondeIntoMinute(wObj["time"]).toStringAsFixed(2)} m",
style: TextStyle( style: TextStyle(
color: TColor.black, color: TColor.black,
fontSize: 12, fontSize: 12,
), ),
), ),
Text( Text(
"Dénivelé positif : ${wObj["DenivelePositif"].toString()}", "Vitesse moyenne : ${Convertisseur.msIntoKmh(wObj["VitesseAvg"]).toStringAsFixed(2)} km/h",
style: TextStyle( style: TextStyle(
color: TColor.black, color: TColor.black,
fontSize: 12, fontSize: 12,

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart'; import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/common_widget/graph/data_for_graph/func_bpm_by_time.dart';
import 'package:smartfit_app_mobile/common_widget/graph/mobile/mobile_altitude_by_time.dart'; import 'package:smartfit_app_mobile/common_widget/graph/mobile/mobile_altitude_by_time.dart';
import 'package:smartfit_app_mobile/common_widget/graph/web/web_altitude_by_time.dart'; import 'package:smartfit_app_mobile/common_widget/graph/web/web_altitude_by_time.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart'; import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
@ -18,9 +19,10 @@ class GraphAltitudeByTime extends StatefulWidget {
class _GraphAltitudeByTime extends State<GraphAltitudeByTime> { class _GraphAltitudeByTime extends State<GraphAltitudeByTime> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final FuncBpmByTime funcBpm = FuncBpmByTime(widget.data);
return ScreenTypeLayout.builder( return ScreenTypeLayout.builder(
mobile: (_) => MobileGraphAltitudeByTime(widget.media, widget.data), mobile: (_) => MobileGraphAltitudeByTime(widget.media, widget.data, funcBpm),
desktop: (_) => WebGraphAltitudeByTime(widget.media, widget.data), desktop: (_) => WebGraphAltitudeByTime(widget.media, widget.data, funcBpm),
); );
} }
} }

@ -21,7 +21,7 @@ class _BpmByTime extends State<BpmByTime> {
final FuncBpmByTime funcBpm = FuncBpmByTime(widget.data); final FuncBpmByTime funcBpm = FuncBpmByTime(widget.data);
return ScreenTypeLayout.builder( return ScreenTypeLayout.builder(
mobile: (_) => MobileBpmByTime(widget.media, widget.data), mobile: (_) => MobileBpmByTime(widget.media, widget.data, funcBpm),
desktop: (_) => WebBpmByTime(widget.media, widget.data, funcBpm), desktop: (_) => WebBpmByTime(widget.media, widget.data, funcBpm),
); );
} }

@ -14,14 +14,14 @@ class FuncBpmAndSpeedByTime {
getTitlesWidget: rightTitleWidgets, getTitlesWidget: rightTitleWidgets,
showTitles: true, showTitles: true,
interval: 20, interval: 20,
reservedSize: 40, reservedSize: 42,
); );
SideTitles get leftTitles => SideTitles( SideTitles get leftTitles => SideTitles(
getTitlesWidget: leftTitleWidgets, getTitlesWidget: leftTitleWidgets,
showTitles: true, showTitles: true,
interval: 20, interval: 20,
reservedSize: 40, reservedSize: 42,
); );
SideTitles get bottomTitles => SideTitles( SideTitles get bottomTitles => SideTitles(
getTitlesWidget: bottomTitleWidgets, getTitlesWidget: bottomTitleWidgets,
@ -79,7 +79,7 @@ class FuncBpmAndSpeedByTime {
return Text(text, return Text(text,
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
fontSize: 12, fontSize: 8,
), ),
textAlign: TextAlign.center); textAlign: TextAlign.center);
} }
@ -113,7 +113,7 @@ class FuncBpmAndSpeedByTime {
return Text(text, return Text(text,
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
fontSize: 12, fontSize: 8,
), ),
textAlign: TextAlign.center); textAlign: TextAlign.center);
} }
@ -148,7 +148,7 @@ class FuncBpmAndSpeedByTime {
return Text(text, return Text(text,
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
fontSize: 12, fontSize: 8,
), ),
textAlign: TextAlign.center); textAlign: TextAlign.center);
} }

@ -67,19 +67,19 @@ class FuncBpmByTime {
text = '0 s'; text = '0 s';
break; break;
case 20: case 20:
text = "${(interval).toStringAsFixed(2)} s"; text = "${(interval).toStringAsFixed(0)} s";
break; break;
case 40: case 40:
text = "${(interval * 2).toStringAsFixed(2)} s"; text = "${(interval * 2).toStringAsFixed(0)} s";
break; break;
case 60: case 60:
text = "${(interval * 3).toStringAsFixed(2)} s"; text = "${(interval * 3).toStringAsFixed(0)} s";
break; break;
case 80: case 80:
text = "${(interval * 4).toStringAsFixed(2)} s"; text = "${(interval * 4).toStringAsFixed(0)} s";
break; break;
case 100: case 100:
text = "${(interval * 5).toStringAsFixed(2)} s"; text = "${(interval * 5).toStringAsFixed(0)} s";
break; break;
default: default:
return Container(); return Container();

@ -2,14 +2,16 @@ import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/graph/data_for_graph/func_bpm_by_time.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart'; import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
class MobileGraphAltitudeByTime extends StatefulWidget { class MobileGraphAltitudeByTime extends StatefulWidget {
final Size media; final Size media;
final DataHomeView data; final DataHomeView data;
final FuncBpmByTime func;
const MobileGraphAltitudeByTime(this.media, this.data, {Key? key}) const MobileGraphAltitudeByTime(this.media, this.data, this.func, {Key? key})
: super(key: key); : super(key: key);
@override @override
@ -70,20 +72,19 @@ class _MobileGraphAltitudeByTime extends State<MobileGraphAltitudeByTime> {
leftTitles: const AxisTitles(), leftTitles: const AxisTitles(),
topTitles: const AxisTitles(), topTitles: const AxisTitles(),
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: widget.func.bottomTitles,
reservedSize: 20, ),
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse((value / 10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles( rightTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
reservedSize: 60, reservedSize: 60,
showTitles: true, showTitles: true,
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
return Text("${double.parse(value.toStringAsFixed(2))} m"); return Text("${double.parse(value.toStringAsFixed(2))} m",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}, },
)), )),
)))); ))));

@ -111,27 +111,16 @@ class _MobileGraphBpmAndSpeedByTime
titlesData: FlTitlesData( titlesData: FlTitlesData(
show: true, show: true,
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: widget.func.rightTitles, sideTitles: widget.func.leftTitles,
), ),
topTitles: const AxisTitles(), topTitles: const AxisTitles(),
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: widget.func.bottomTitles,
reservedSize: 20, ),
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse((value / 10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles( rightTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: widget.func.rightTitles,
reservedSize: 70,
showTitles: true, ),),
getTitlesWidget: (value, meta) {
return Text(
"${double.parse(value.toStringAsFixed(2))} BPM");
},
))),
gridData: FlGridData( gridData: FlGridData(
drawVerticalLine: true, drawVerticalLine: true,
drawHorizontalLine: true, drawHorizontalLine: true,

@ -1,13 +1,15 @@
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/graph/data_for_graph/func_bpm_by_time.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart'; import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
class MobileBpmByTime extends StatefulWidget { class MobileBpmByTime extends StatefulWidget {
final Size media; final Size media;
final DataHomeView data; final DataHomeView data;
final FuncBpmByTime func;
const MobileBpmByTime(this.media, this.data, {Key? key}) : super(key: key); const MobileBpmByTime(this.media, this.data,this.func, {Key? key}) : super(key: key);
@override @override
State<MobileBpmByTime> createState() => _MobileBpmByTime(); State<MobileBpmByTime> createState() => _MobileBpmByTime();
@ -57,19 +59,19 @@ class _MobileBpmByTime extends State<MobileBpmByTime> {
leftTitles: const AxisTitles(), leftTitles: const AxisTitles(),
topTitles: const AxisTitles(), topTitles: const AxisTitles(),
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: widget.func.bottomTitles,
reservedSize: 20, ),
showTitles: true,
getTitlesWidget: (value, meta) {
return Text("${double.parse((value/10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles( rightTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
reservedSize: 70, reservedSize: 70,
showTitles: true, showTitles: true,
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
return Text("${double.parse(value.toStringAsFixed(2))} BPM"); return Text("${double.parse(value.toStringAsFixed(2))} BPM",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}, },
)), )),
)))); ))));

@ -2,14 +2,16 @@ import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/graph/data_for_graph/func_bpm_by_time.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart'; import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
class WebGraphAltitudeByTime extends StatefulWidget { class WebGraphAltitudeByTime extends StatefulWidget {
final Size media; final Size media;
final DataHomeView data; final DataHomeView data;
final FuncBpmByTime func;
const WebGraphAltitudeByTime(this.media, this.data, {Key? key}) const WebGraphAltitudeByTime(this.media, this.data, this.func, {Key? key})
: super(key: key); : super(key: key);
@override @override
@ -69,20 +71,19 @@ class _WebGraphAltitudeByTime extends State<WebGraphAltitudeByTime> {
leftTitles: const AxisTitles(), leftTitles: const AxisTitles(),
topTitles: const AxisTitles(), topTitles: const AxisTitles(),
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: widget.func.bottomTitles,
reservedSize: 20, ),
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse((value / 10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles( rightTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
reservedSize: 60, reservedSize: 60,
showTitles: true, showTitles: true,
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
return Text("${double.parse(value.toStringAsFixed(2))} m"); return Text("${double.parse(value.toStringAsFixed(2))} m",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}, },
)), )),
)))); ))));

@ -9,7 +9,7 @@ class Steps extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
String steps = Provider.of<User>(context, listen: false) String steps = Provider.of<User>(context, listen: false)
.managerSelectedActivity .managerSelectedActivity
.getTimeAllActivitySelected() .getStepsAllActivitySelected()
.toString(); .toString();
return Padding( return Padding(

@ -39,8 +39,8 @@ class MyApp extends StatelessWidget {
stdout.write("===== USER =====\n"); stdout.write("===== USER =====\n");
stdout.write("Username: ${user.username}\n"); stdout.write("Username: ${user.username}\n");
stdout.write("Username: ${user.email}\n"); stdout.write("Email: ${user.email}\n");
stdout.write("Username: ${user.token}\n"); stdout.write("Token: ${user.token}\n");
viewToDisplay = const MainTabView(); viewToDisplay = const MainTabView();
} }

@ -3,7 +3,7 @@ import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
class ActivityOfUser { class ActivityOfUser {
final ActivityInfo _activityInfo; final ActivityInfo _activityInfo;
// A afficher // A afficher
final String _categorie; final String _category;
final String _fileUuid; final String _fileUuid;
final String _nameFile; final String _nameFile;
// ------------ // // ------------ //
@ -14,7 +14,7 @@ class ActivityOfUser {
String get fileUuid => _fileUuid; String get fileUuid => _fileUuid;
String get nameFile => _nameFile; String get nameFile => _nameFile;
String get category => _categorie; String get category => _category;
ActivityInfo get activityInfo => _activityInfo; ActivityInfo get activityInfo => _activityInfo;
Map<String, int> get enteteCSV => _enteteCSV; Map<String, int> get enteteCSV => _enteteCSV;
@ -29,9 +29,9 @@ class ActivityOfUser {
} }
ActivityOfUser( ActivityOfUser(
this._activityInfo, this._categorie, this._fileUuid, this._nameFile) { this._activityInfo, this._category, this._fileUuid, this._nameFile) {
// Mettre dans une fonction appart // Mettre dans une fonction appart
if (_categorie == "Walking") { if (_category == "Walking") {
_imageName = "assets/img/workout1.svg"; _imageName = "assets/img/workout1.svg";
} else { } else {
// Mettre des conditions pour d'autre type d'activité // Mettre des conditions pour d'autre type d'activité
@ -43,7 +43,7 @@ class ActivityOfUser {
Map<String, dynamic> toMapGeneric() { Map<String, dynamic> toMapGeneric() {
Map<String, dynamic> map = { Map<String, dynamic> map = {
'categorie': _categorie, 'categorie': _category,
'image': _imageName, 'image': _imageName,
'date': _activityInfo.startTime, 'date': _activityInfo.startTime,
'time': _activityInfo.timeOfActivity, 'time': _activityInfo.timeOfActivity,

@ -16,6 +16,7 @@ class ActivityInfo {
int bpmMax = 0; int bpmMax = 0;
int bpmMin = 300; int bpmMin = 300;
int bpmAvg = 0; int bpmAvg = 0;
bool bpmNotZero = false;
// ----------- Denivelé ------------ // // ----------- Denivelé ------------ //
double denivelePositif = 0.0; double denivelePositif = 0.0;
double deniveleNegatif = 0.0; double deniveleNegatif = 0.0;
@ -23,19 +24,22 @@ class ActivityInfo {
double altitudeMax = 0.0; double altitudeMax = 0.0;
double altitudeMin = 30000.0; double altitudeMin = 30000.0;
double altitudeAvg = 0.0; double altitudeAvg = 0.0;
bool altitudeNotZero = false;
// ----------- Température --------- // // ----------- Température --------- //
int temperatureMax = 0; int temperatureMax = 0;
int temperatureMin = 3000; int temperatureMin = 3000;
int temperatureAvg = 0; int temperatureAvg = 0;
bool temperatureNotZero = false;
// ----------- Vitesse ------------- // // ----------- Vitesse ------------- //
double vitesseMax = 0.0; double vitesseMax = 0.0;
double vitesseMin = 999999.0; double vitesseMin = 999999.0;
double vitesseAvg = 0.0; double vitesseAvg = 0.0;
bool vitesseNotZero = false;
// ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- //
// -- Fonction pour lire le csv et remplir la classe -- // // -- Fonction pour lire le csv et remplir la classe -- //
ActivityInfo getData(List<List<String>> csv) { ActivityInfo getDataWalking(List<List<String>> csv) {
// - Entete - // // - Entete - //
Map<String, int> enteteCSV = getEntete(csv.first); Map<String, int> enteteCSV = getEntete(csv.first);
// ------------- Var tmp ---------- // // ------------- Var tmp ---------- //
@ -63,6 +67,7 @@ class ActivityInfo {
int.parse(csv[i][enteteCSV["Value_${managerFile.fielBPM}"]!]); int.parse(csv[i][enteteCSV["Value_${managerFile.fielBPM}"]!]);
bpmSomme += value; bpmSomme += value;
bpmNb += 1; bpmNb += 1;
bpmNotZero = true;
if (value > bpmMax) { if (value > bpmMax) {
bpmMax = value; bpmMax = value;
} }
@ -91,6 +96,7 @@ class ActivityInfo {
} }
altitudeSomme += value; altitudeSomme += value;
alititudeNb += 1; alititudeNb += 1;
altitudeNotZero = true;
} }
// ------------------------ Température ----------------------- // // ------------------------ Température ----------------------- //
@ -100,6 +106,7 @@ class ActivityInfo {
csv[i][enteteCSV["Value_${managerFile.fieldTemperature}"]!]); csv[i][enteteCSV["Value_${managerFile.fieldTemperature}"]!]);
temperatureSomme += value; temperatureSomme += value;
temperatureNb += 1; temperatureNb += 1;
temperatureNotZero = true;
if (value > temperatureMax) { if (value > temperatureMax) {
temperatureMax = value; temperatureMax = value;
} }
@ -114,6 +121,7 @@ class ActivityInfo {
double.parse(csv[i][enteteCSV["Value_${managerFile.fieldSpeed}"]!]); double.parse(csv[i][enteteCSV["Value_${managerFile.fieldSpeed}"]!]);
vitesseSomme += value; vitesseSomme += value;
vitesseNb += 1; vitesseNb += 1;
vitesseNotZero = true;
if (value > vitesseMax) { if (value > vitesseMax) {
vitesseMax = value; vitesseMax = value;
} }
@ -124,13 +132,168 @@ class ActivityInfo {
} }
// -- BPM -- // // -- BPM -- //
bpmAvg = bpmSomme ~/ bpmNb; if (bpmNotZero) {
bpmAvg = bpmSomme ~/ bpmNb;
}
// -- Atitude -- //
if (altitudeNotZero) {
altitudeAvg = altitudeSomme / alititudeNb;
}
// -- Température -- //
if (temperatureNotZero) {
temperatureAvg = temperatureSomme ~/ temperatureNb;
}
// -- Vitesse -- //
if (vitesseNotZero) {
vitesseAvg = vitesseSomme / vitesseNb;
}
return this;
}
// -- Fonction pour lire le csv et remplir la classe -- //
ActivityInfo getDataCycling(List<List<String>> csv) {
// - Entete - //
Map<String, int> enteteCSV = getEntete(csv.first);
// ------------- Var tmp ---------- //
// -- BPM -- //
int bpmSomme = 0;
int bpmNb = 0;
// -- Denivelé -- //
double lastDenivele = 0.0;
// -- Altitude -- //
double altitudeSomme = 0;
int alititudeNb = 0;
// -- Température -- //
int temperatureSomme = 0;
int temperatureNb = 0;
// -- Vitesse -- //
double vitesseSomme = 0.0;
int vitesseNb = 0;
// --- Boucle -- //
for (int i = 1; i < csv.length; i++) {
//
// ---------------------- BPM ---------------------- //
if (!isNull(enteteCSV["Value_${managerFile.fielBPM}"]!, csv[i])) {
int value =
int.parse(csv[i][enteteCSV["Value_${managerFile.fielBPM}"]!]);
bpmSomme += value;
bpmNb += 1;
bpmNotZero = true;
if (value > bpmMax) {
bpmMax = value;
}
if (value < bpmMin) {
bpmMin = value;
}
}
/// ------------------ Denivele et Altitude --------------- //
if (!isNull(enteteCSV["Value_${managerFile.fieldAltitude}"]!, csv[i])) {
double value = double.parse(
csv[i][enteteCSV["Value_${managerFile.fieldAltitude}"]!]);
// -- Denivelé -- //
if (value > lastDenivele) {
denivelePositif += value - lastDenivele;
} else {
deniveleNegatif += (value - lastDenivele) * -1;
}
lastDenivele = value;
// -- Altitude -- //
if (value > altitudeMax) {
altitudeMax = value;
}
if (value < altitudeMin) {
altitudeMin = value;
}
altitudeSomme += value;
alititudeNb += 1;
altitudeNotZero = true;
}
// ------------------------ Température ----------------------- //
if (!isNull(
enteteCSV["Value_${managerFile.fieldTemperature}"]!, csv[i])) {
int value = int.parse(
csv[i][enteteCSV["Value_${managerFile.fieldTemperature}"]!]);
temperatureSomme += value;
temperatureNb += 1;
vitesseNotZero = true;
if (value > temperatureMax) {
temperatureMax = value;
}
if (value < temperatureMin) {
temperatureMin = value;
}
}
// ------------------------ Vitesse -----------------------------//
if (!isNull(enteteCSV["Value_${managerFile.fieldSpeed}"]!, csv[i])) {
double value =
double.parse(csv[i][enteteCSV["Value_${managerFile.fieldSpeed}"]!]);
vitesseSomme += value;
vitesseNb += 1;
vitesseNotZero = true;
if (value > vitesseMax) {
vitesseMax = value;
}
if (value < vitesseMin) {
vitesseMin = value;
}
}
}
// -- BPM -- //
if (bpmNotZero) {
bpmAvg = bpmSomme ~/ bpmNb;
}
// -- Atitude -- // // -- Atitude -- //
altitudeAvg = altitudeSomme / alititudeNb; if (altitudeNotZero) {
altitudeAvg = altitudeSomme / alititudeNb;
}
// -- Température -- // // -- Température -- //
temperatureAvg = temperatureSomme ~/ temperatureNb; if (temperatureNotZero) {
temperatureAvg = temperatureSomme ~/ temperatureNb;
}
// -- Vitesse -- // // -- Vitesse -- //
vitesseAvg = vitesseSomme / vitesseNb; if (vitesseNotZero) {
vitesseAvg = vitesseSomme / vitesseNb;
}
return this;
}
// -- Fonction pour lire le csv et remplir la classe -- //
ActivityInfo getDataGeneric(List<List<String>> csv) {
// - Entete - //
Map<String, int> enteteCSV = getEntete(csv.first);
// ------------- Var tmp ---------- //
// -- BPM -- //
int bpmSomme = 0;
int bpmNb = 0;
bool bpmNotZero = false;
// --- Boucle -- //
for (int i = 1; i < csv.length; i++) {
//
// ---------------------- BPM ---------------------- //
if (!isNull(enteteCSV["Value_${managerFile.fielBPM}"]!, csv[i])) {
int value =
int.parse(csv[i][enteteCSV["Value_${managerFile.fielBPM}"]!]);
bpmSomme += value;
bpmNb += 1;
bpmNotZero = true;
if (value > bpmMax) {
bpmMax = value;
}
if (value < bpmMin) {
bpmMin = value;
}
}
}
// -- BPM -- //
if (bpmNotZero) {
bpmAvg = bpmSomme ~/ bpmNb;
}
return this; return this;
} }
@ -156,7 +319,9 @@ class ActivityInfo {
// -- Altitude -- // // -- Altitude -- //
"AltitudeMax": altitudeMax, "AltitudeMax": altitudeMax,
"AltitudeMin": altitudeMin, "AltitudeMin": altitudeMin,
"AltitudeAvg": altitudeAvg "AltitudeAvg": altitudeAvg,
// -- Vitesse -- //
"VitesseAvg": vitesseAvg
}; };
} }
@ -167,30 +332,106 @@ class ActivityInfo {
return; return;
} }
// -- Ligne session -- // // -- Ligne session -- //
startTime = DateTime.parse(map["startTime"]); try {
timeOfActivity = map["timeOfActivity"].toDouble(); startTime = DateTime.parse(map["startTime"]);
distance = map["distance"].toDouble(); } catch (e) {
calories = map["calories"].toInt(); print("Impossible de recup -> startTime");
steps = map["steps"].toInt(); }
try {
timeOfActivity = map["timeOfActivity"];
} catch (e) {
print("Impossible de recup -> timeOfActivity");
}
try {
distance = map["distance"].toDouble();
} catch (e) {
print("Impossible de recup -> distance");
}
try {
calories = map["calories"];
} catch (e) {
print("Impossible de recup -> calories");
}
try {
steps = map["steps"];
} catch (e) {
print("Impossible de recup -> steps");
}
// -- BPM -- // // -- BPM -- //
bpmAvg = map["bpmAvg"]; try {
bpmMax = map["bpmMax"]; bpmAvg = map["bpmAvg"];
bpmMin = map["bpmMin"]; } catch (e) {
print("Impossible de recup -> ");
}
try {
bpmMax = map["bpmMax"];
} catch (e) {
print("Impossible de recup -> ");
}
try {
bpmMin = map["bpmMin"];
} catch (e) {
print("Impossible de recup -> ");
}
// -- Denivelé -- // // -- Denivelé -- //
deniveleNegatif = map["deniveleNegatif"].toDouble(); try {
denivelePositif = map["denivelePositif"].toDouble(); deniveleNegatif = map["deniveleNegatif"];
} catch (e) {
print("Impossible de recup -> deniveleNegatif");
}
try {
denivelePositif = map["denivelePositif"];
} catch (e) {
print("Impossible de recup -> denivelePositif");
}
// -- Altitude -- // // -- Altitude -- //
altitudeMax = map["altitudeMax"].toDouble(); try {
altitudeMin = map["altitudeMin"].toDouble(); altitudeMax = map["altitudeMax"];
altitudeAvg = map["altitudeAvg"].toDouble(); } catch (e) {
print("Impossible de recup -> altitudeMax");
}
try {
altitudeMin = map["altitudeMin"];
} catch (e) {
print("Impossible de recup -> altitudeMin");
}
try {
altitudeAvg = map["altitudeAvg"];
} catch (e) {
print("Impossible de recup -> altitudeAvg");
}
// -- Température -- // // -- Température -- //
temperatureMax = map["temperatureMax"].toInt(); try {
temperatureMin = map["temperatureMin"].toInt(); temperatureMax = map["temperatureMax"];
temperatureAvg = map["temperatureAvg"].toInt(); } catch (e) {
print("Impossible de recup -> temperatureMax");
}
try {
temperatureMin = map["temperatureMin"];
} catch (e) {
print("Impossible de recup -> temperatureMin");
}
try {
temperatureAvg = map["temperatureAvg"];
} catch (e) {
print("Impossible de recup -> temperatureAvg");
}
// -- Vitesse -- // // -- Vitesse -- //
vitesseMax = map["vitesseMax"].toDouble(); try {
vitesseMin = map["vitesseMin"].toDouble(); vitesseMax = map["vitesseMax"].toDouble();
vitesseAvg = map["vitesseAvg"].toDouble(); } catch (e) {
print("Impossible de recup -> vitesseMax");
}
try {
vitesseMin = map["vitesseMin"].toDouble();
} catch (e) {
print("Impossible de recup -> vitesseMin");
}
try {
vitesseAvg = map["vitesseAvg"].toDouble();
} catch (e) {
print("Impossible de recup -> vitesseAvg");
}
} }
// -- Ecriture -- // // -- Ecriture -- //
@ -216,7 +457,7 @@ class ActivityInfo {
'vitesseMin': vitesseMin, 'vitesseMin': vitesseMin,
'vitesseAvg': vitesseAvg, 'vitesseAvg': vitesseAvg,
// Ligne session // Ligne session
'startTime': startTime.toString(), 'startTime': startTime.toIso8601String(),
'timeOfActivity': timeOfActivity, 'timeOfActivity': timeOfActivity,
'distance': distance, 'distance': distance,
'calories': calories, 'calories': calories,

@ -1,10 +1,9 @@
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import "package:path_provider/path_provider.dart";
import 'package:smartfit_app_mobile/modele/helper.dart'; import 'package:smartfit_app_mobile/main.dart';
class ActivitySaver { class ActivitySaver {
String saveDirectory = "activities"; String saveDirectory = "activities";
@ -12,21 +11,33 @@ class ActivitySaver {
ActivitySaver._create(this.applicationDocumentsDir); ActivitySaver._create(this.applicationDocumentsDir);
static Future<ActivitySaver> create() async { Uint8List getActivity(String uuid) {
final appDir = await getApplicationDocumentsDirectory(); String filename = localDB.getActivityFilenameByUuid(uuid);
return ActivitySaver._create(appDir);
final file =
File(p.join(applicationDocumentsDir.path, saveDirectory, filename));
return file.readAsBytesSync();
} }
Future<void> saveActivity(Uint8List activityFile, String filename) async { Future<void> saveActivity(Uint8List activityFile, String filename) async {
stdout.write("Creating activity file...\n");
final file = await File( final file = await File(
p.join(applicationDocumentsDir.path, saveDirectory, filename)) p.join(applicationDocumentsDir.path, saveDirectory, filename))
.create(recursive: true); // To create dir if not exists .create(recursive: true); // To create dir if not exists
file.writeAsBytesSync(activityFile); file.writeAsBytesSync(activityFile);
stdout.write("Activity file created\n");
} }
File getActivity(String filename) { void deleteActivity(String uuid) {
String filename = localDB.getActivityFilenameByUuid(uuid);
final file = final file =
File(p.join(applicationDocumentsDir.path, saveDirectory, filename)); File(p.join(applicationDocumentsDir.path, saveDirectory, filename));
return file; file.deleteSync();
}
static Future<ActivitySaver> create() async {
stdout.write("Activity Saver: Created\n");
final appDir = await getApplicationDocumentsDirectory();
return ActivitySaver._create(appDir);
} }
} }

@ -9,6 +9,7 @@ import 'package:email_validator/email_validator.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
import 'dart:convert'; import 'dart:convert';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'dart:io'; import 'dart:io';
class ApiWrapper { class ApiWrapper {
@ -34,9 +35,12 @@ class ApiWrapper {
if (await isOnline()) { if (await isOnline()) {
stdout.write("(API) "); stdout.write("(API) ");
api = RequestApi(); api = RequestApi();
} else { } else if (localDB.getSaveLocally()) {
stdout.write("(LOCAL) "); stdout.write("(LOCAL) ");
api = RequestLocal(); api = RequestLocal();
} else {
stdout.write("(API OFFLINE) ");
api = RequestApi();
} }
} }
@ -57,18 +61,27 @@ class ApiWrapper {
return res; return res;
} }
Future<Tuple2> getFile(String token, String fileUuid) async { Future<Tuple2> getFile(
String token, String fileUuid, InfoMessage infoManager) async {
await init(); await init();
Tuple2 res = await api.getFile(token, fileUuid); Tuple2 res = await api.getFile(token, fileUuid);
if (!res.item1) {
infoManager.displayMessage(noConnectionMessage, true);
}
stdout.write("getFile: ${res.item1}\n"); stdout.write("getFile: ${res.item1}\n");
return res; return res;
} }
Future<Tuple2> getFiles(String token) async { Future<Tuple2> getFiles(String token, InfoMessage infoManager) async {
await init(); await init();
Tuple2 res = await api.getFiles(token); Tuple2 res = await api.getFiles(token);
if (!res.item1) {
infoManager.displayMessage(noConnectionMessage, true);
}
stdout.write("getFiles: ${res.item1}\n"); stdout.write("getFiles: ${res.item1}\n");
return res; return res;
} }
@ -110,7 +123,7 @@ class ApiWrapper {
String hash = sha256.convert(utf8.encode(password)).toString(); String hash = sha256.convert(utf8.encode(password)).toString();
Tuple2<bool, String> res = await api.connexion(email, hash); Tuple2<bool, String> res = await api.connexion(email, hash);
stdout.write("login: ${res.item1}"); stdout.write("login: ${res.item1}\n");
if (res.item1) { if (res.item1) {
return Tuple2(true, res.item2); return Tuple2(true, res.item2);
} else { } else {
@ -128,7 +141,7 @@ class ApiWrapper {
Tuple2<bool, String> res = await api.deleteUser(token); Tuple2<bool, String> res = await api.deleteUser(token);
stdout.write("deleteUser: ${res.item1}"); stdout.write("deleteUser: ${res.item1}\n");
return res; return res;
} }
@ -139,7 +152,7 @@ class ApiWrapper {
Tuple2<bool, String> res = await api.postUser(email, hash, username); Tuple2<bool, String> res = await api.postUser(email, hash, username);
stdout.write("createUser: ${res.item1}"); stdout.write("createUser: ${res.item1}\n");
return res; return res;
} }
@ -149,7 +162,7 @@ class ApiWrapper {
if (handleOffline(infoManager)) return const Tuple2(false, "offline"); if (handleOffline(infoManager)) return const Tuple2(false, "offline");
Tuple2<bool, String> res = await api.uploadFile(token, file); Tuple2<bool, String> res = await api.uploadFile(token, file);
stdout.write("uploadFile: ${res.item1}"); stdout.write("uploadFile: ${res.item1}\n");
return res; return res;
} }
@ -166,7 +179,9 @@ class ApiWrapper {
Tuple2<bool, String> res = await api.uploadFileByte( Tuple2<bool, String> res = await api.uploadFileByte(
token, contentFile, filename, category, date, activityInfo); token, contentFile, filename, category, date, activityInfo);
stdout.write("uploadFileByte: ${res.item1}"); if (!res.item1) infoManager.displayMessage(noConnectionMessage, true);
stdout.write("uploadFileByte: ${res.item1}\n");
return res; return res;
} }
@ -176,8 +191,9 @@ class ApiWrapper {
if (handleOffline(infoManager)) return false; if (handleOffline(infoManager)) return false;
bool res = await api.deleteFile(token, fileUuid); bool res = await api.deleteFile(token, fileUuid);
if (!res) infoManager.displayMessage(noConnectionMessage, true);
stdout.write("deleteFile: ${res}"); stdout.write("deleteFile: $res\n");
return res; return res;
} }
} }

@ -19,36 +19,44 @@ class RequestApi implements IDataStrategy {
var request = http.Request('GET', url); var request = http.Request('GET', url);
request.headers.addAll(<String, String>{'Authorization': token}); request.headers.addAll(<String, String>{'Authorization': token});
var streamedResponse = await request.send(); try {
final response = await http.Response.fromStream(streamedResponse); var streamedResponse = await request.send();
// !! Crée un fichier comme ca avec les bytes !! final response = await http.Response.fromStream(streamedResponse);
//File("//").writeAsBytes(response.bodyBytes);
if (response.statusCode == 200) { if (response.statusCode == 200) {
return Tuple2(true, response.bodyBytes); return Tuple2(true, response.bodyBytes);
} }
if ((response.statusCode == 401)) { if ((response.statusCode == 401)) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
} }
if ((response.statusCode == 404)) { if ((response.statusCode == 404)) {
return const Tuple2(false, "404 - NOT FOUND"); return const Tuple2(false, "404 - NOT FOUND");
}
// When Network Off
} on SocketException {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@override @override
Future<bool> deleteFile(String token, String fileUuid) async { Future<bool> deleteFile(String token, String fileUuid) async {
final response = await http.delete( try {
Uri.parse('$urlApi/user/files/$fileUuid'), final response = await http.delete(
headers: <String, String>{'Authorization': token}); Uri.parse('$urlApi/user/files/$fileUuid'),
headers: <String, String>{'Authorization': token});
if (response.statusCode == 200) { if (response.statusCode == 200) {
return true; return true;
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return false; return false;
} }
if (response.statusCode == 404) { if (response.statusCode == 404) {
return false;
}
} on SocketException catch (_) {
return false; return false;
} }
return false; return false;
@ -56,48 +64,60 @@ class RequestApi implements IDataStrategy {
@override @override
Future<Tuple2<bool, String>> deleteUser(String token) async { Future<Tuple2<bool, String>> deleteUser(String token) async {
final response = await http.delete(Uri.parse('$urlApi/user'), try {
headers: <String, String>{'Authorization': token}); final response = await http.delete(Uri.parse('$urlApi/user'),
if (response.statusCode == 200) { headers: <String, String>{'Authorization': token});
return const Tuple2<bool, String>(true, "Successful"); if (response.statusCode == 200) {
} else if (response.statusCode == 401) { return const Tuple2<bool, String>(true, "Successful");
return const Tuple2<bool, String>( } else if (response.statusCode == 401) {
false, "401 UNAUTHORIZED - Mauvais ou pas de token"); return const Tuple2<bool, String>(
} else if (response.statusCode == 404) { false, "401 UNAUTHORIZED - Mauvais ou pas de token");
return const Tuple2<bool, String>( } else if (response.statusCode == 404) {
false, "404 NOT FOUND - Pas de compte lié"); return const Tuple2<bool, String>(
false, "404 NOT FOUND - Pas de compte lié");
}
} on SocketException catch (_) {
return const Tuple2<bool, String>(false, "No connection");
} }
return const Tuple2<bool, String>(false, "Fail"); return const Tuple2<bool, String>(false, "Fail");
} }
@override @override
Future<Tuple2> getFiles(String token) async { Future<Tuple2> getFiles(String token) async {
final response = await http.get(Uri.parse('$urlApi/user/files'), try {
headers: <String, String>{'Authorization': token}); final response = await http.get(Uri.parse('$urlApi/user/files'),
headers: <String, String>{'Authorization': token});
if (response.statusCode == 200) { if (response.statusCode == 200) {
return Tuple2(true, return Tuple2(true,
(json.decode(response.body) as List).cast<Map<String, dynamic>>()); (json.decode(response.body) as List).cast<Map<String, dynamic>>());
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@override @override
Future<Tuple2<bool, String>> connexion(String email, String hash) async { Future<Tuple2<bool, String>> connexion(String email, String hash) async {
final response = try {
await http.get(Uri.parse('$urlApi/user/login/$email/$hash')); final response =
if (response.statusCode == 200) { await http.get(Uri.parse('$urlApi/user/login/$email/$hash'));
Map<String, dynamic> json = jsonDecode(response.body); if (response.statusCode == 200) {
return Tuple2<bool, String>(true, json['token'].toString()); Map<String, dynamic> json = jsonDecode(response.body);
} return Tuple2<bool, String>(true, json['token'].toString());
if (response.statusCode == 401) { }
return const Tuple2<bool, String>(false, "UNAUTHORIZED"); if (response.statusCode == 401) {
} return const Tuple2<bool, String>(false, "UNAUTHORIZED");
if (response.statusCode == 404) { }
return const Tuple2<bool, String>(false, "Not found the email"); if (response.statusCode == 404) {
return const Tuple2<bool, String>(false, "Not found the email");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@ -107,19 +127,23 @@ class RequestApi implements IDataStrategy {
String email, String hash, String username) async { String email, String hash, String username) async {
var body = {"email": email, "hash": hash, "username": username}; var body = {"email": email, "hash": hash, "username": username};
var header = {"Content-Type": "application/json"}; var header = {"Content-Type": "application/json"};
final response = await http.post(Uri.parse('$urlApi/user'), try {
headers: header, body: jsonEncode(body)); final response = await http.post(Uri.parse('$urlApi/user'),
headers: header, body: jsonEncode(body));
if (response.statusCode == 200) { if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(response.body); Map<String, dynamic> json = jsonDecode(response.body);
return Tuple2(true, json['token'].toString()); return Tuple2(true, json['token'].toString());
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 BAD REQUEST - Json mal formaté"); return const Tuple2(false, "400 BAD REQUEST - Json mal formaté");
} }
if (response.statusCode == 409) { if (response.statusCode == 409) {
return const Tuple2( return const Tuple2(
false, "409 CONFLICT - Déja un compte avec cet email"); false, "409 CONFLICT - Déja un compte avec cet email");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@ -127,25 +151,28 @@ class RequestApi implements IDataStrategy {
@override @override
Future<Tuple2<bool, String>> modifAttribut( Future<Tuple2<bool, String>> modifAttribut(
String token, String nameAttribut, String newValue) async { String token, String nameAttribut, String newValue) async {
final response = await http.put(Uri.parse('$urlApi/user/$nameAttribut'), try {
headers: <String, String>{ final response = await http.put(Uri.parse('$urlApi/user/$nameAttribut'),
'Authorization': token, headers: <String, String>{
"Content-Type": "application/json" 'Authorization': token,
}, "Content-Type": "application/json"
body: jsonEncode(<String, String>{nameAttribut: newValue})); },
body: jsonEncode(<String, String>{nameAttribut: newValue}));
if (response.statusCode == 200) {
//Map<String, dynamic> json = jsonDecode(response.body); if (response.statusCode == 200) {
return const Tuple2(true, "200 - OK"); //Map<String, dynamic> json = jsonDecode(response.body);
} return const Tuple2(true, "200 - OK");
if (response.statusCode == 400) { }
return const Tuple2(false, "400 - BAD REQUEST"); if (response.statusCode == 400) {
} return const Tuple2(false, "400 - BAD REQUEST");
if (response.statusCode == 401) { }
return const Tuple2(false, "400 - UNAUTHORIZED"); if (response.statusCode == 401) {
} else { return const Tuple2(false, "400 - UNAUTHORIZED");
return const Tuple2(false, "Fail"); }
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail");
} }
// -- Priviligié uploadFileByte -- // // -- Priviligié uploadFileByte -- //
@ -169,19 +196,23 @@ class RequestApi implements IDataStrategy {
request.fields["SmartFit_Category"] = categoryActivity; request.fields["SmartFit_Category"] = categoryActivity;
request.fields["SmartFit_Date"] = dateActivity; request.fields["SmartFit_Date"] = dateActivity;
final response = await request.send(); try {
final response = await request.send();
if (response.statusCode == 200) { if (response.statusCode == 200) {
return const Tuple2(true, "Successful"); return const Tuple2(true, "Successful");
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 - BAD REQUEST"); return const Tuple2(false, "400 - BAD REQUEST");
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
} }
if (response.statusCode == 409) { if (response.statusCode == 409) {
return const Tuple2(false, "409 - CONFLICT"); return const Tuple2(false, "409 - CONFLICT");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail "); return const Tuple2(false, "Fail ");
} }
@ -209,36 +240,44 @@ class RequestApi implements IDataStrategy {
request.fields["SmartFit_Date"] = date.toString(); request.fields["SmartFit_Date"] = date.toString();
request.fields["info"] = activityInfo.toJson(); request.fields["info"] = activityInfo.toJson();
final response = await request.send(); try {
final response = await request.send();
if (response.statusCode == 200) { if (response.statusCode == 200) {
return const Tuple2(true, "Successful"); return const Tuple2(true, "Successful");
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 - BAD REQUEST"); return const Tuple2(false, "400 - BAD REQUEST");
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
} }
if (response.statusCode == 409) { if (response.statusCode == 409) {
return const Tuple2(false, "409 - CONFLICT"); return const Tuple2(false, "409 - CONFLICT");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail "); return const Tuple2(false, "Fail ");
} }
@override @override
Future<Tuple2> getInfoUser(String token) async { Future<Tuple2> getInfoUser(String token) async {
final response = await http.get(Uri.parse('$urlApi/user/info'), try {
headers: <String, String>{'Authorization': token}); final response = await http.get(Uri.parse('$urlApi/user/info'),
if (response.statusCode == 200) { headers: <String, String>{'Authorization': token});
Map<String, dynamic> json = jsonDecode(response.body); if (response.statusCode == 200) {
return Tuple2(true, json); Map<String, dynamic> json = jsonDecode(response.body);
} return Tuple2(true, json);
if (response.statusCode == 400) { }
return const Tuple2(false, "400 - BAD REQUEST"); if (response.statusCode == 400) {
} return const Tuple2(false, "400 - BAD REQUEST");
if (response.statusCode == 401) { }
return const Tuple2(false, "401 - UNAUTHORIZED"); if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }

@ -0,0 +1,11 @@
class Convertisseur {
// Mettre que des trucs static
static double secondeIntoMinute(double seconde) {
return seconde / 60;
}
static double msIntoKmh(double metreSeconde) {
return metreSeconde * 3.6;
}
}

@ -14,7 +14,6 @@ class User {
@Entity() @Entity()
class Activity { class Activity {
int id; int id;
@Unique() @Unique()
String uuid; String uuid;
String filename; String filename;
@ -23,3 +22,12 @@ class Activity {
Activity(this.id, this.uuid, this.filename, this.category, this.info); Activity(this.id, this.uuid, this.filename, this.category, this.info);
} }
@Entity()
class Config {
@Id()
int id = 0;
bool saveLocally;
Config(this.id, this.saveLocally);
}

@ -1,8 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data';
import 'package:csv/csv.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart'; import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/objectbox.g.dart'; import 'package:smartfit_app_mobile/objectbox.g.dart';
@ -14,7 +12,7 @@ class ObjectBox {
late final Store store; late final Store store;
late final Box userBox; late final Box userBox;
late final Box activityBox; late final Box activityBox;
late final String activitiesSavePath = "activities"; late final Box configBox;
late final Directory applicationDocumentDir; late final Directory applicationDocumentDir;
ObjectBox._create(this.store); ObjectBox._create(this.store);
@ -29,6 +27,7 @@ class ObjectBox {
applicationDocumentDir = await getApplicationDocumentsDirectory(); applicationDocumentDir = await getApplicationDocumentsDirectory();
userBox = store.box<User>(); userBox = store.box<User>();
activityBox = store.box<Activity>(); activityBox = store.box<Activity>();
configBox = store.box<Config>();
} }
// ===== USER ===== // ===== USER =====
@ -73,8 +72,19 @@ class ObjectBox {
} }
} }
void removeActivity(int uuid) { // TODO: try catch
activityBox.remove(uuid); void removeActivity(String uuid) {
final Query query = activityBox.query(Activity_.uuid.equals(uuid)).build();
final Activity act = query.findFirst();
activityBox.remove(act.id);
}
String getActivityFilenameByUuid(String uuid) {
final Query query = activityBox.query(Activity_.uuid.equals(uuid)).build();
final Activity act = query.findFirst();
return act.filename;
} }
List<Activity> getAllActivities() { List<Activity> getAllActivities() {
@ -87,21 +97,6 @@ class ObjectBox {
} }
// ===== FIT Files ===== // ===== FIT Files =====
Future<void> saveActivityFile(List<List<dynamic>> activityFile) async {
String csv = const ListToCsvConverter().convert(activityFile);
Uint8List csvAsBytes = Uint8List.fromList(utf8.encode(csv));
final file =
await File(p.join(applicationDocumentDir.path, activitiesSavePath))
.create();
file.writeAsBytesSync(csvAsBytes);
}
File getActivityFile(String filename) {
final file =
File(p.join(applicationDocumentDir.path, activitiesSavePath, filename));
return file;
}
List<ActivityOfUser> loadActivities() { List<ActivityOfUser> loadActivities() {
List<dynamic> activityDBList = activityBox.getAll(); List<dynamic> activityDBList = activityBox.getAll();
List<ActivityOfUser> userActivityList = List.empty(growable: true); List<ActivityOfUser> userActivityList = List.empty(growable: true);
@ -114,4 +109,18 @@ class ObjectBox {
return userActivityList; return userActivityList;
} }
// ===== Config =====
void setSaveLocally(bool saveLocally) {
Config config = configBox.get(1);
config.saveLocally = saveLocally;
configBox.put(config);
stdout.write("(Config) setSaveLocally: $saveLocally\n");
}
bool getSaveLocally() {
Config config = configBox.get(1);
stdout.write("(Config) getSaveLocally: ${config.saveLocally}\n");
return config.saveLocally;
}
} }

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart'; import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/activity_saver.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart'; import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/local_db/model.dart'; import 'package:smartfit_app_mobile/modele/local_db/model.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -18,7 +19,10 @@ class RequestLocal implements IDataStrategy {
// need to save file on request_api.upload() beforehand. // need to save file on request_api.upload() beforehand.
@override @override
Future<Tuple2> getFile(String token, String fileUuid) async { Future<Tuple2> getFile(String token, String fileUuid) async {
return const Tuple2(true, "to implement"); ActivitySaver actSaver = await ActivitySaver.create();
Uint8List fileBytes = actSaver.getActivity(fileUuid);
return Tuple2(true, fileBytes);
} }
@override @override

@ -113,7 +113,7 @@ class ManagerFile {
categorie = categorie =
_getCategoryById(int.parse(_getXfromListe(_sport, ligneSession))); _getCategoryById(int.parse(_getXfromListe(_sport, ligneSession)));
// -- Si la catégorie est pas prévu est est généric -- // // -- Si la catégorie est pas prévu == généric -- //
switch (categorie) { switch (categorie) {
case (_marche): case (_marche):
fieldAllowed = allowedFieldWalking; fieldAllowed = allowedFieldWalking;
@ -137,15 +137,24 @@ class ManagerFile {
// ------ Remplir info avec la ligne session --------- // // ------ Remplir info avec la ligne session --------- //
info.startTime = DateTime.fromMillisecondsSinceEpoch( info.startTime = DateTime.fromMillisecondsSinceEpoch(
int.parse(_getXfromListe(_startTime, ligneSession))); int.parse(_getXfromListe(_startTime, ligneSession)));
info.timeOfActivity = info.timeOfActivity =
double.parse(_getXfromListe(_timeActivity, ligneSession)); double.parse(_getXfromListe(_timeActivity, ligneSession));
info.distance = double.parse(_getXfromListe(_totalDistance, ligneSession)); info.distance = double.parse(_getXfromListe(_totalDistance, ligneSession));
info.calories = int.parse(_getXfromListe(_totalCalories, ligneSession)); info.calories = int.parse(_getXfromListe(_totalCalories, ligneSession));
info.steps = int.parse(_getXfromListe(_totalStep, ligneSession)); info.steps = int.parse(_getXfromListe(_totalStep, ligneSession));
// ----------------------------------------------------- // // ----------------------------------------------------- //
// -- Extraire les données en fonction de la catégorie -- //
switch (categorie) {
case (_marche):
info.getDataWalking(csvData);
case (_velo):
info.getDataCycling(csvData);
default:
info.getDataGeneric(csvData);
}
return Tuple4(true, csvData, info.getData(csvData), categorie); //print("Fin : ManagerFile -> convertBytesFitFileIntoCSVListAndGetInfo ");
return Tuple4(true, csvData, info, categorie);
} }
List<dynamic> _getLigneSession(List<Record> listRecord) { List<dynamic> _getLigneSession(List<Record> listRecord) {
@ -164,7 +173,7 @@ class ManagerFile {
return liste[i + 1].toString(); return liste[i + 1].toString();
} }
} }
return "null"; return "0";
} }
List<Map<String, Map<String, String>>> getDataOfListeOfRecord( List<Map<String, Map<String, String>>> getDataOfListeOfRecord(

@ -37,7 +37,7 @@ class User extends ChangeNotifier {
// ------------ Walking -------------- // // ------------ Walking -------------- //
// ---- Denivelé ---- // // ---- Denivelé ---- //
double getTotalDenivelePositif() { double getTotalDenivelePositifAllActivity() {
double totalDevPos = 0.0; double totalDevPos = 0.0;
for (ActivityOfUser activity in listActivity) { for (ActivityOfUser activity in listActivity) {
totalDevPos += activity.activityInfo.denivelePositif; totalDevPos += activity.activityInfo.denivelePositif;
@ -45,7 +45,7 @@ class User extends ChangeNotifier {
return totalDevPos; return totalDevPos;
} }
double getTotalDeniveleNegatif() { double getTotalDeniveleNegatifAllActivity() {
double totalDevNeg = 0.0; double totalDevNeg = 0.0;
for (ActivityOfUser activity in listActivity) { for (ActivityOfUser activity in listActivity) {
totalDevNeg += activity.activityInfo.deniveleNegatif; totalDevNeg += activity.activityInfo.deniveleNegatif;

@ -22,7 +22,7 @@ class HomeViewUtil {
List<FlSpot> bpmSecondes2 = List.from(bpmSecondes); List<FlSpot> bpmSecondes2 = List.from(bpmSecondes);
return DataHomeView(normaliserPremierElement(bpmSecondes), normaliserPremierElement(normaliserDeuxiemeElement(bpmSecondes2)), return DataHomeView(normaliserPremierElement(bpmSecondes), normaliserPremierElement(normaliserDeuxiemeElement(bpmSecondes2)),
normaliserPremierElement(normaliserDeuxiemeElement(vitesseSecondes)), altitudeSeconde); normaliserPremierElement(normaliserDeuxiemeElement(vitesseSecondes)), normaliserPremierElement(altitudeSeconde));
} }
List<FlSpot> normaliserDeuxiemeElement(List<FlSpot> liste) { List<FlSpot> normaliserDeuxiemeElement(List<FlSpot> liste) {

@ -11,8 +11,6 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart'; import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart'; import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart'; import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
@ -22,11 +20,12 @@ class ListActivityUtile {
final ApiWrapper api = ApiWrapper(); final ApiWrapper api = ApiWrapper();
final ManagerFile _managerFile = ManagerFile(); final ManagerFile _managerFile = ManagerFile();
Future<Tuple2<bool, String>> getContentActivity( Future<Tuple2<bool, String>> getContentActivity(BuildContext context,
BuildContext context, ActivityOfUser activityOfUser) async { ActivityOfUser activityOfUser, InfoMessage infoManager) async {
Tuple2 result = await api.getFile( Tuple2 result = await api.getFile(
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
activityOfUser.fileUuid); activityOfUser.fileUuid,
infoManager);
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(result.item1, result.item2); return Tuple2(result.item1, result.item2);
} }
@ -37,6 +36,14 @@ class ListActivityUtile {
// TODO: Not sure this line as an utility // TODO: Not sure this line as an utility
// localDB.saveActivityFile(activityOfUser.contentActivity); // localDB.saveActivityFile(activityOfUser.contentActivity);
// TODO: Check if file exists, right now it overwrites each time
// TODO: Make ActivitySaver member of the class
if (!Helper.isPlatformWeb() && localDB.getSaveLocally()) {
ActivitySaver actSaver = await ActivitySaver.create();
actSaver.saveActivity(result.item2,
localDB.getActivityFilenameByUuid(activityOfUser.fileUuid));
}
if (!Provider.of<User>(context, listen: false) if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity .managerSelectedActivity
.addSelectedActivity(activityOfUser)) { .addSelectedActivity(activityOfUser)) {
@ -46,10 +53,10 @@ class ListActivityUtile {
} }
Future<Tuple2<bool, String>> getFiles( Future<Tuple2<bool, String>> getFiles(
String token, BuildContext context) async { String token, BuildContext context, InfoMessage infoManager) async {
bool notZero = false; bool notZero = false;
Tuple2 result = Tuple2 result = await api.getFiles(
await api.getFiles(Provider.of<User>(context, listen: false).token); Provider.of<User>(context, listen: false).token, infoManager);
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(result.item1, result.item2); return Tuple2(result.item1, result.item2);
} }
@ -68,18 +75,13 @@ class ListActivityUtile {
element["filename"].toString())); element["filename"].toString()));
// Save to local db // Save to local db
localDB.addActivity(db.Activity( localDB.addActivity(db.Activity(0, element["uuid"], element["filename"],
0, element["category"], jsonEncode(element["info"])));
element["uuid"],
element["filename"],
element["category"],
element["info"]
.toString())); // TODO: Do not remove toString(), it do not work w/o it, idk why
} }
return const Tuple2(true, "Yeah"); return const Tuple2(true, "Yeah");
} }
Future<Tuple2<bool, String>> _addFile(Uint8List bytes, String filename, Future<Tuple2<bool, String>> addFile(Uint8List bytes, String filename,
String token, InfoMessage infoManager) async { String token, InfoMessage infoManager) async {
// -- Transormer le fit en CSV // -- Transormer le fit en CSV
Tuple4<bool, List<List<String>>, ActivityInfo, String> resultData = Tuple4<bool, List<List<String>>, ActivityInfo, String> resultData =
@ -88,55 +90,58 @@ class ListActivityUtile {
String csvString = const ListToCsvConverter().convert(resultData.item2); String csvString = const ListToCsvConverter().convert(resultData.item2);
Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString)); Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString));
// Save on local storage if plateform not browser
if (!Helper.isPlatformWeb()) {
ActivitySaver actSaver = await ActivitySaver.create();
actSaver.saveActivity(byteCSV, filename);
}
Tuple2<bool, String> result = await api.uploadFileByte( Tuple2<bool, String> result = await api.uploadFileByte(
token, token,
byteCSV, byteCSV,
filename, filename,
resultData.item4, resultData.item4, // category
resultData.item3.startTime, resultData.item3.startTime, // activityInfo
resultData.item3, resultData.item3,
infoManager); infoManager);
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(false, result.item2); return Tuple2(false, result.item2);
} }
// Save on local storage if plateform not browser
if (!Helper.isPlatformWeb() && localDB.getSaveLocally()) {
ActivitySaver actSaver = await ActivitySaver.create();
actSaver.saveActivity(byteCSV, filename);
}
return const Tuple2(true, "Yeah"); return const Tuple2(true, "Yeah");
} }
// --- Ne marche pas sous window !! Jsp linux (mettre en format mobile) -- // // --- Ne marche pas sous windows !! Jsp linux (mettre en format mobile) -- //
void addFileWeb(Uint8List? bytes, String token, String filename, Future<void> addFileWeb(Uint8List? bytes, String token, String filename,
BuildContext context, InfoMessage infoManager) async { BuildContext context, InfoMessage infoManager) async {
if (bytes == null) { if (bytes == null) {
return; return;
} }
Tuple2<bool, String> resultAdd = Tuple2<bool, String> resultAdd =
await _addFile(bytes, filename, token, infoManager); await addFile(bytes, filename, token, infoManager);
if (!resultAdd.item1) { if (!resultAdd.item1) {
//print("Message error"); //print("Message error");
return; return;
} }
Tuple2<bool, String> resultGet = await getFiles(token, context); Tuple2<bool, String> resultGet =
await getFiles(token, context, infoManager);
if (!resultGet.item1) { if (!resultGet.item1) {
//print("Message error"); //print("Message error");
return; return;
} }
} }
void addFileMobile(String path, String token, String filename, Future<void> addFileMobile(String path, String token, String filename,
BuildContext context, InfoMessage infoManager) async { BuildContext context, InfoMessage infoManager) async {
Tuple2<bool, String> resultAdd = await _addFile( Tuple2<bool, String> resultAdd = await addFile(
await File(path).readAsBytes(), filename, token, infoManager); await File(path).readAsBytes(), filename, token, infoManager);
if (!resultAdd.item1) { if (!resultAdd.item1) {
//print("Message error"); //print("Message error");
return; return;
} }
// TODO: What is that ? // TODO: What is that ?
Tuple2<bool, String> resultGet = await getFiles(token, context); Tuple2<bool, String> resultGet =
await getFiles(token, context, infoManager);
if (!resultGet.item1) { if (!resultGet.item1) {
//print("Message error"); //print("Message error");
return; return;

@ -29,7 +29,7 @@ class _MobileListActivity extends State<MobileListActivity> {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
@ -43,9 +43,13 @@ class _MobileListActivity extends State<MobileListActivity> {
fontWeight: FontWeight.w700), fontWeight: FontWeight.w700),
), ),
TextButton( TextButton(
onPressed: () => _utile.getFiles( onPressed: () async {
Provider.of<User>(context, listen: false).token, await _utile.getFiles(
context), Provider.of<User>(context, listen: false).token,
context,
infoManager);
setState(() {});
},
child: Text("Get activity", child: Text("Get activity",
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
@ -56,17 +60,18 @@ class _MobileListActivity extends State<MobileListActivity> {
FilePickerResult? result = FilePickerResult? result =
await FilePicker.platform.pickFiles(); await FilePicker.platform.pickFiles();
if (result != null && result.files.isNotEmpty) { if (result != null && result.files.isNotEmpty) {
// ignore: use_build_context_synchronously await _utile.addFileMobile(
_utile.addFileMobile(
result.files.single.path!, result.files.single.path!,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
result.files.first.name, result.files.first.name,
context, context,
infoManager); infoManager);
setState(() {});
} else { } else {
// msg d'erreur // msg d'erreur
// User canceled the picker // User canceled the picker
} }
setState(() {});
}, },
child: Text( child: Text(
"Ajouter", "Ajouter",

@ -29,7 +29,7 @@ class _WebListActivityState extends State<WebListActivity> {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
@ -43,9 +43,13 @@ class _WebListActivityState extends State<WebListActivity> {
fontWeight: FontWeight.w700), fontWeight: FontWeight.w700),
), ),
TextButton( TextButton(
onPressed: () => _utile.getFiles( onPressed: () async {
Provider.of<User>(context, listen: false).token, await _utile.getFiles(
context), Provider.of<User>(context, listen: false).token,
context,
infoManager);
setState(() {});
},
child: Text("Get activity", child: Text("Get activity",
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
@ -56,7 +60,7 @@ class _WebListActivityState extends State<WebListActivity> {
FilePickerResult? result = FilePickerResult? result =
await FilePicker.platform.pickFiles(); await FilePicker.platform.pickFiles();
if (result != null && result.files.isNotEmpty) { if (result != null && result.files.isNotEmpty) {
_utile.addFileWeb( await _utile.addFileWeb(
result.files.first.bytes, result.files.first.bytes,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
result.files.first.name, result.files.first.name,
@ -78,6 +82,10 @@ class _WebListActivityState extends State<WebListActivity> {
) )
], ],
), ),
Visibility(
visible: infoManager.isVisible,
child: Text(infoManager.message,
style: TextStyle(color: infoManager.messageColor))),
Provider.of<User>(context, listen: true).listActivity.isEmpty Provider.of<User>(context, listen: true).listActivity.isEmpty
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

@ -47,7 +47,8 @@ class _MobileHomeView extends State<MobileHomeView> {
// -- Speed -- // // -- Speed -- //
double maxSpeed = managerSelectedActivity.getMaxSpeedAllActivitySelected(); double maxSpeed = managerSelectedActivity.getMaxSpeedAllActivitySelected();
double avgSpeed = managerSelectedActivity.getAvgSpeedAllActivitySelected(); double avgSpeed = managerSelectedActivity.getAvgSpeedAllActivitySelected();
data.maxSpeed = maxSpeed;
data.time = context.watch<User>().managerSelectedActivity.getTimeAllActivitySelected();
return Scaffold( return Scaffold(
backgroundColor: TColor.white, backgroundColor: TColor.white,
body: SingleChildScrollView( body: SingleChildScrollView(

@ -172,6 +172,7 @@ class _WebLoginView extends State<WebLoginView> {
util.fillUser(context, infoUser.item2, result.item2); util.fillUser(context, infoUser.item2, result.item2);
localDB.userBox.put(User(0, infoUser.item2["username"], localDB.userBox.put(User(0, infoUser.item2["username"],
infoUser.item2["email"], result.item2)); infoUser.item2["email"], result.item2));
localDB.configBox.put(Config(0, false));
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(

@ -92,8 +92,8 @@ class _MobileMainTabViewState extends State<MobileMainTabView> {
width: 40, width: 40,
), ),
TabButton( TabButton(
icon: "assets/img/Camera_tab.svg", icon: "assets/img/mapIcon.svg",
selectIcon: "assets/img/Camera_tab_select.svg", selectIcon: "assets/img/mapIcon_selected.svg",
isActive: selectTab == 2, isActive: selectTab == 2,
onTap: () { onTap: () {
selectTab = 2; selectTab = 2;

@ -76,8 +76,8 @@ class _WebMainTabViewState extends State<WebMainTabView> {
), ),
), ),
sideBarButton( sideBarButton(
icon: "assets/img/icon_map.svg", icon: "assets/img/mapIcon.svg",
selectIcon: "assets/img/icon_map.svg", selectIcon: "assets/img/mapIcon_selected.svg",
index: 2, index: 2,
onTap: () => updateTab(2, const MyMap()), onTap: () => updateTab(2, const MyMap()),
), ),

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/button/round_button.dart';
import 'package:smartfit_app_mobile/view/map/mobile/mobile_my_map.dart'; import 'package:smartfit_app_mobile/view/map/mobile/mobile_my_map.dart';
import 'package:smartfit_app_mobile/view/map/my_map_osm.dart'; import 'package:smartfit_app_mobile/view/map/my_map_osm.dart';
@ -13,6 +15,58 @@ class ChoseMap extends StatefulWidget {
class _ChoseMap extends State<ChoseMap> { class _ChoseMap extends State<ChoseMap> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SafeArea(
child: Center(
// Utilisation du widget Center pour centrer verticalement
child: Container(
width: media.width,
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize
.min, // Utilisation de MainAxisSize.min pour que la colonne prenne la hauteur minimale nécessaire
children: [
SizedBox(
height: media.height * 0.1,
),
SvgPicture.asset(
"assets/img/group.svg",
width: media.width * 0.75,
height: media.height * 0.4,
fit: BoxFit.fitWidth,
),
SizedBox(
height: media.height * 0.1,
),
RoundButton(
title: "Use map with google map",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MobileMyMaps()));
},
),
SizedBox(
height: media.height * 0.03,
),
RoundButton(
title : "Use map with Open Street Map",
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const MyMapOSM()));
},
),
Spacer(),
],
),
),
),
),
);
return Scaffold( return Scaffold(
backgroundColor: TColor.white, backgroundColor: TColor.white,
body: SafeArea( body: SafeArea(
@ -20,20 +74,7 @@ class _ChoseMap extends State<ChoseMap> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MobileMyMaps()));
},
child: const Text("Use map with google map")),
TextButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const MyMapOSM()));
},
child: const Text("Use map with Open Street Map")),
const Text( const Text(
"Mettre une image la en mode une personne avec des jumelles") "Mettre une image la en mode une personne avec des jumelles")
], ],

@ -25,7 +25,7 @@ class _MobileMyMaps extends State<MobileMyMaps> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text("Carte Google Map "), title: const Text("Carte Google Map "),
backgroundColor: TColor.primaryColor1, backgroundColor: TColor.secondaryColor1,
), ),
body: _getMap()); body: _getMap());
} }

@ -23,7 +23,7 @@ class _MyMapOSM extends State<MyMapOSM> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text("Carte Open Street Map "), title: const Text("Carte Open Street Map "),
backgroundColor: TColor.primaryColor1, backgroundColor: TColor.secondaryColor1,
), ),
body: FlutterMap( body: FlutterMap(
options: MapOptions(center: listPolynines.first), options: MapOptions(center: listPolynines.first),

@ -1,19 +1,19 @@
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_switch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_compte.dart'; import 'package:smartfit_app_mobile/common_widget/container/profile/profile_compte.dart';
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_entete.dart'; import 'package:smartfit_app_mobile/common_widget/container/profile/profile_entete.dart';
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_info_user.dart'; import 'package:smartfit_app_mobile/common_widget/container/profile/profile_info_user.dart';
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_notification.dart';
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_other.dart'; import 'package:smartfit_app_mobile/common_widget/container/profile/profile_other.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
class ProfileViewAllPlatforme extends StatefulWidget { class ProfileViewAllPlatforme extends StatefulWidget {
final bool positive; final bool offlineSave;
final List accountArr; final List accountArr;
final List otherArr; final List otherArr;
const ProfileViewAllPlatforme(this.positive, this.accountArr, this.otherArr, const ProfileViewAllPlatforme(
this.offlineSave, this.accountArr, this.otherArr,
{super.key}); {super.key});
@override @override
@ -36,26 +36,6 @@ class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> {
style: TextStyle( style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700), color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
), ),
actions: [
InkWell(
onTap: () {},
child: Container(
margin: const EdgeInsets.all(8),
height: 20,
width: 20,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.lightGray,
borderRadius: BorderRadius.circular(10)),
child: Image.asset(
"assets/img/more_btn.png",
width: 15,
height: 15,
fit: BoxFit.contain,
),
),
)
],
), ),
backgroundColor: TColor.white, backgroundColor: TColor.white,
body: SingleChildScrollView( body: SingleChildScrollView(
@ -76,7 +56,10 @@ class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> {
const SizedBox( const SizedBox(
height: 25, height: 25,
), ),
ProfileNotification(widget.positive), // TODO: Download/Delete (local) all users files on toggle ?
// TODO: Display size of download in Mo
const ProfileSwitch(
"Offline mode", "Save your files locally", "local_save.png"),
const SizedBox( const SizedBox(
height: 25, height: 25,
), ),

@ -62,6 +62,7 @@ dependencies:
path: ^1.8.3 path: ^1.8.3
flutter_map: ^5.0.0 flutter_map: ^5.0.0
latlong2: ^0.9.0 latlong2: ^0.9.0
units_converter: ^2.1.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save