Compare commits

...

22 Commits

Author SHA1 Message Date
remrem ece19ef7d2 translate common_widget
continuous-integration/drone/push Build is passing Details
2 years ago
remrem cd6c43431e translate view/volumes
continuous-integration/drone/push Build was killed Details
2 years ago
remrem 8ee5055ffc translate view/profile
continuous-integration/drone/push Build was killed Details
2 years ago
remrem a2657b2bba translate view/on_boarding
continuous-integration/drone/push Build was killed Details
2 years ago
remrem 8b65bccf9f translate view/map
continuous-integration/drone/push Build was killed Details
2 years ago
remrem 3e00d74e97 fix ci
continuous-integration/drone/push Build is passing Details
2 years ago
remrem 6e2b6c057e conflicts with stats_activities_view.dart
continuous-integration/drone/push Build was killed Details
2 years ago
remrem 359cbfeed8 translate view/login
2 years ago
remrem d15eb2bffc rename strings fr to en in view/{activity,home}
2 years ago
remrem a10439d1bc rewrite string message in request_api
continuous-integration/drone/push Build is failing Details
2 years ago
Enzo 4a40f1bbd6 Merge branch 'Enzo'
continuous-integration/drone/push Build is failing Details
2 years ago
Enzo 866a0a7381 change convertisseur
2 years ago
Othmane BENJELLOUN 0784a95f3a Merge branch 'master' of https://codefirst.iut.uca.fr/git/SmartFit/SmartFit_Mobile
continuous-integration/drone/push Build is failing Details
2 years ago
Othmane BENJELLOUN 147c53e1ae regle affichage
2 years ago
Enzo c5b182411e Merge branch 'master' into Enzo
2 years ago
remrem acdb0ce770 add files for github actions
continuous-integration/drone/push Build is passing Details
2 years ago
Enzo dcd2198e79 correction affichage predict
2 years ago
Enzo 404c5f344a coorectif web import
2 years ago
Enzo ad706516df Merge branch 'Enzo'
continuous-integration/drone/push Build is passing Details
2 years ago
Enzo e2e5f86e3c remove print
2 years ago
Enzo 5f46882c18 correction import sur generic
2 years ago
Enzo 97e915d31f bug file généric
2 years ago

@ -19,10 +19,6 @@ steps:
- dart run build_runner clean
- dart run build_runner build --delete-conflicting-outputs
- flutter build apk
- sfm_apk=sfm_$(date +"%Y_%m_%d_%H_%M_%S").apk
- cp ./build/app/outputs/flutter-apk/app-release.apk $sfm_apk
- curl -F "file=@$sfm_apk" https://anonfiles.me/api/v1/upload > upload.json
- cat upload.json | cut -d '"' -f 12
- name: build-web
image: ghcr.io/cirruslabs/flutter:3.16.3

@ -0,0 +1,38 @@
name: Flutter CI
on:
push:
branches: [ master ]
jobs:
build-apk-web-sonarqube:
runs-on: ubuntu-latest
container: ghcr.io/cirruslabs/flutter:3.16.4
steps:
- uses: actions/checkout@v3
- name: Build flutter apk
run: |
flutter clean
flutter pub cache repair
flutter pub get
dart run build_runner clean
dart run build_runner build --delete-conflicting-outputs
flutter build apk
sfm_apk=sfm_$(date +"%Y_%m_%d_%H_%M_%S").apk
cp ./build/app/outputs/flutter-apk/app-release.apk $sfm_apk
curl -F "file=@$sfm_apk" https://anonfiles.me/api/v1/upload > upload.json
cat upload.json | cut -d '"' -f 12
- name: Build flutter web
run: |
flutter build web --web-renderer canvaskit
curl -sL https://firebase.tools | bash
- name: Code analysis
run: |
export SONAR_SCANNER_VERSION=5.0.1.3006
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export SONAR_SCANNER_OPTS="-server"

@ -12,7 +12,7 @@ class VolumesList extends StatelessWidget {
// TODO: True message with variables and context aware
if (volume["nbActivity"] == 0) {
return const Text("Aucune activité ces x jours/mois/années");
return const Text("No activity the last x days/month/year");
}
return SingleChildScrollView(
@ -21,32 +21,32 @@ class VolumesList extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(volume["nbActivity"].toString(),
"Nombre Activitée(s)", Icons.numbers),
"Number of activities", Icons.numbers),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"${Convertisseur.secondeIntoMinute(volume["durationActiviy"]).toStringAsFixed(2)} m",
"Temps Total",
"${Convertisseur.secondeIntoMinute(volume["durationActiviy"]).toStringAsFixed(0)} min",
"Total time",
Icons.timer),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
volume["bpmAvg"].toString(), "Bpm Moyens", Icons.favorite),
volume["bpmAvg"].toString(), "Average bpm", Icons.favorite),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
" ${Convertisseur.msIntoKmh(volume["speedAvg"]).toStringAsFixed(2)} km/h",
"Vitesse Moyenne",
"Average speed",
Icons.bolt),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"${volume["denivelePositif"].toStringAsFixed(2)} m",
"Dénivelé Positif",
"Positive height difference",
Icons.hiking),
],
),

@ -38,7 +38,7 @@ class MobileLigneContainerStats extends StatelessWidget {
child: Row(
children: [
const Text(
'Statistiques',
'Stats',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w800,

@ -22,7 +22,7 @@ class ProfileCompte extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Compte",
"Account",
style: TextStyle(
color: TColor.black,
fontSize: 16,

@ -35,7 +35,7 @@ class ProfileEntete extends StatelessWidget {
),
),
Text(
"Course à pied",
"Running",
style: TextStyle(
color: TColor.gray,
fontSize: 12,

@ -13,7 +13,7 @@ class ProfileInfoUser extends StatelessWidget {
Expanded(
child: TitleSubtitleCell(
title: context.watch<User>().listActivity.length.toString(),
subtitle: "Nombre d'activité",
subtitle: "Number of activities",
),
),
const SizedBox(
@ -21,8 +21,11 @@ class ProfileInfoUser extends StatelessWidget {
),
Expanded(
child: TitleSubtitleCell(
title: context.watch<User>().getTotalTimeAllActivity().toStringAsFixed(2),
subtitle: "Temps en activité",
title: context
.watch<User>()
.getTotalTimeAllActivity()
.toStringAsFixed(2),
subtitle: "Total activity time",
),
),
const SizedBox(
@ -32,7 +35,7 @@ class ProfileInfoUser extends StatelessWidget {
child: TitleSubtitleCell(
title:
"${context.watch<User>().getTotalDenivelePositifAllActivity().toStringAsFixed(2)} + m",
subtitle: "Total dénivelé positif",
subtitle: "Total positive height difference",
),
),
const SizedBox(
@ -42,7 +45,7 @@ class ProfileInfoUser extends StatelessWidget {
child: TitleSubtitleCell(
title:
"${context.watch<User>().getTotalDeniveleNegatifAllActivity().toStringAsFixed(2)} - m",
subtitle: "Total dénivelé négatif",
subtitle: "Total negative height difference",
),
),
],

@ -21,7 +21,7 @@ class ProfileOther extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Autre",
"Others",
style: TextStyle(
color: TColor.black,
fontSize: 16,

@ -37,7 +37,7 @@ class WebLigneContainerStats extends StatelessWidget {
child: Column(
children: [
const Text(
'Statistiques',
'Stats',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w800,

@ -27,31 +27,32 @@ class WorkoutRow extends StatelessWidget {
fit: BoxFit.cover,
),
),
const SizedBox(width: 15,),
const SizedBox(
width: 15,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
Text(
wObj["name"].toString(),
style: TextStyle(
color: TColor.black,
fontSize: 15,
fontWeight: FontWeight.bold),
),
Text(
"${ wObj["value"].toString()}",
wObj["value"].toString(),
style: TextStyle(
color: TColor.gray,
fontSize: 12,),
color: TColor.gray,
fontSize: 12,
),
),
const SizedBox(
height: 4,
),
const SizedBox(height: 4,),
],
)),
],
));
}

@ -75,7 +75,7 @@ class WorkoutRowGeneric extends StatelessWidget {
),
),
Text(
"Temps : ${Convertisseur.secondeIntoMinute(wObj["time"]).toStringAsFixed(2)} m",
"Time : ${Convertisseur.secondeIntoMinute(wObj["time"]).toStringAsFixed(2)} m",
style: TextStyle(
color: TColor.black,
fontSize: 12,

@ -75,14 +75,14 @@ class WorkoutRowWalking extends StatelessWidget {
),
),
Text(
"Temps : ${Convertisseur.secondeIntoMinute(wObj["time"]).toStringAsFixed(2)} m",
"Time : ${Convertisseur.secondeIntoMinute(wObj["time"]).toStringAsFixed(0)} minutes",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
Text(
"Vitesse moyenne : ${Convertisseur.msIntoKmh(wObj["VitesseAvg"]).toStringAsFixed(2)} km/h",
"Average speed : ${Convertisseur.msIntoKmh(wObj["VitesseAvg"]).toStringAsFixed(2)} km/h",
style: TextStyle(
color: TColor.black,
fontSize: 12,

@ -36,75 +36,8 @@ class _MobileGraphBpmAndSpeedByTime
width: double.maxFinite,
child: LineChart(
LineChartData(
showingTooltipIndicators:
widget.func.showingTooltipOnSpots.map((index) {
return ShowingTooltipIndicators([
LineBarSpot(
widget.func.tooltipsOnBar,
widget.func.lineBarsData.indexOf(widget.func.tooltipsOnBar),
widget.func.tooltipsOnBar.spots[index],
),
]);
}).toList(),
lineTouchData: LineTouchData(
enabled: true,
handleBuiltInTouches: false,
touchCallback: (FlTouchEvent event, LineTouchResponse? response) {
if (response == null || response.lineBarSpots == null) {
return;
}
if (event is FlTapUpEvent) {
final spotIndex = response.lineBarSpots!.first.spotIndex;
widget.func.showingTooltipOnSpots.clear();
setState(() {
widget.func.showingTooltipOnSpots.add(spotIndex);
});
}
},
mouseCursorResolver:
(FlTouchEvent event, LineTouchResponse? response) {
if (response == null || response.lineBarSpots == null) {
return SystemMouseCursors.basic;
}
return SystemMouseCursors.click;
},
getTouchedSpotIndicator:
(LineChartBarData barData, List<int> spotIndexes) {
return spotIndexes.map((index) {
return TouchedSpotIndicatorData(
const FlLine(
color: Colors.transparent,
),
FlDotData(
show: true,
getDotPainter: (spot, percent, barData, index) =>
FlDotCirclePainter(
radius: 3,
color: Colors.white,
strokeWidth: 3,
strokeColor: TColor.secondaryColor1,
),
),
);
}).toList();
},
touchTooltipData: LineTouchTooltipData(
tooltipBgColor: TColor.secondaryColor1,
tooltipRoundedRadius: 20,
getTooltipItems: (List<LineBarSpot> lineBarsSpot) {
return lineBarsSpot.map((lineBarSpot) {
return LineTooltipItem(
"Seconde ${lineBarSpot.x.toInt() / 10} ",
const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
);
}).toList();
},
),
),
lineBarsData: widget.func.lineBarsData1,
minY: 0,
maxY: 110,

@ -33,75 +33,7 @@ class _WebGraphBpmAndSpeedByTime extends State<WebGraphBpmAndSpeedByTime> {
width: widget.media.width * 0.35,
child: LineChart(
LineChartData(
showingTooltipIndicators:
widget.func.showingTooltipOnSpots.map((index) {
return ShowingTooltipIndicators([
LineBarSpot(
widget.func.tooltipsOnBar,
widget.func.lineBarsData.indexOf(widget.func.tooltipsOnBar),
widget.func.tooltipsOnBar.spots[index],
),
]);
}).toList(),
lineTouchData: LineTouchData(
enabled: true,
handleBuiltInTouches: false,
touchCallback: (FlTouchEvent event, LineTouchResponse? response) {
if (response == null || response.lineBarSpots == null) {
return;
}
if (event is FlTapUpEvent) {
final spotIndex = response.lineBarSpots!.first.spotIndex;
widget.func.showingTooltipOnSpots.clear();
setState(() {
widget.func.showingTooltipOnSpots.add(spotIndex);
});
}
},
mouseCursorResolver:
(FlTouchEvent event, LineTouchResponse? response) {
if (response == null || response.lineBarSpots == null) {
return SystemMouseCursors.basic;
}
return SystemMouseCursors.click;
},
getTouchedSpotIndicator:
(LineChartBarData barData, List<int> spotIndexes) {
return spotIndexes.map((index) {
return TouchedSpotIndicatorData(
const FlLine(
color: Colors.transparent,
),
FlDotData(
show: true,
getDotPainter: (spot, percent, barData, index) =>
FlDotCirclePainter(
radius: 3,
color: Colors.white,
strokeWidth: 3,
strokeColor: TColor.secondaryColor1,
),
),
);
}).toList();
},
touchTooltipData: LineTouchTooltipData(
tooltipBgColor: TColor.secondaryColor1,
tooltipRoundedRadius: 20,
getTooltipItems: (List<LineBarSpot> lineBarsSpot) {
return lineBarsSpot.map((lineBarSpot) {
return LineTooltipItem(
"Seconde ${lineBarSpot.x.toInt() / 10} ",
const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
);
}).toList();
},
),
),
lineBarsData: widget.func.lineBarsData1,
minY: -10,
maxY: 110,

@ -16,7 +16,7 @@ class EnteteHomeView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Bienvenue,",
"Welcome,",
style: TextStyle(color: TColor.gray, fontSize: 12),
),
Text(

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/convertisseur.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
@ -19,10 +20,11 @@ class Stats extends StatelessWidget {
.activityInfo
.bpmAvg
.toString();
String time = Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getTimeAllActivitySelected()
.toString();
String time = Convertisseur.secondeIntoMinute(
Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getTimeAllActivitySelected())
.toStringAsFixed(0);
return Column(
children: [
Padding(
@ -30,7 +32,7 @@ class Stats extends StatelessWidget {
child: Row(
children: [
const Text(
'Statistiques',
'Stats',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w800,
@ -57,7 +59,7 @@ class Stats extends StatelessWidget {
iconBackground: const Color(0xff6131AD),
time: '+5s',
label: 'Time',
value: '$time s',
value: '$time min',
),
const SizedBox(width: 15),
InfoStat(

@ -1,4 +1,3 @@
import 'package:flutter_svg/flutter_svg.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:flutter/material.dart';
@ -7,7 +6,11 @@ class TodayTargetCell extends StatelessWidget {
final String icon;
final String value;
final String title;
const TodayTargetCell({super.key, required this.icon, required this.value, required this.title});
const TodayTargetCell(
{super.key,
required this.icon,
required this.value,
required this.title});
@override
Widget build(BuildContext context) {
@ -21,7 +24,7 @@ class TodayTargetCell extends StatelessWidget {
child: Row(
children: [
SvgPicture.asset(
icon,
icon,
width: 40,
height: 40,
),
@ -65,3 +68,4 @@ class TodayTargetCell extends StatelessWidget {
);
}
}

@ -270,7 +270,18 @@ class ActivityInfo {
// -- BPM -- //
int bpmSomme = 0;
int bpmNb = 0;
bool bpmNotZero = false;
// -- 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++) {
//
@ -288,12 +299,78 @@ class ActivityInfo {
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;
temperatureNotZero = 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 -- //
if (altitudeNotZero) {
altitudeAvg = altitudeSomme / alititudeNb;
}
// -- Température -- //
if (temperatureNotZero) {
temperatureAvg = temperatureSomme ~/ temperatureNb;
}
// -- Vitesse -- //
if (vitesseNotZero) {
vitesseAvg = vitesseSomme / vitesseNb;
}
return this;
}

@ -111,10 +111,12 @@ class RequestApi implements IDataStrategy {
return Tuple2<bool, String>(true, json['token'].toString());
}
if (response.statusCode == 401) {
return const Tuple2<bool, String>(false, "UNAUTHORIZED");
return const Tuple2<bool, String>(
false, "Wrong Password, enter it carrefully !");
}
if (response.statusCode == 404) {
return const Tuple2<bool, String>(false, "Not found the email");
return const Tuple2<bool, String>(
false, "Account not found, please verify your credentials.");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
@ -136,11 +138,12 @@ class RequestApi implements IDataStrategy {
return Tuple2(true, json['token'].toString());
}
if (response.statusCode == 400) {
return const Tuple2(false, "400 BAD REQUEST - Json mal formaté");
return const Tuple2(false,
"L'application rendontre une erreur inconnue, veuillez réessayer.");
}
if (response.statusCode == 409) {
return const Tuple2(
false, "409 CONFLICT - Déja un compte avec cet email");
false, "Un compte est déjà enregistré avec cet email!");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
@ -267,7 +270,7 @@ class RequestApi implements IDataStrategy {
final response = await http.get(Uri.parse('$urlApi/user/info'),
headers: <String, String>{'Authorization': token});
if (response.statusCode == 200) {
Map<String,dynamic> json = jsonDecode(response.body);
Map<String, dynamic> json = jsonDecode(response.body);
return Tuple2(true, json);
}

@ -12,4 +12,8 @@ class Convertisseur {
static double msIntoKmh(double metreSeconde) {
return metreSeconde * 3.6;
}
static double millisecondeIntoSeconde(double milliseconde) {
return (milliseconde / 1000);
}
}

@ -62,7 +62,16 @@ class ManagerFile {
_fieldTemperature
];
allowedFieldGeneric = [_fieldTimestamp, _fieldBPM];
allowedFieldGeneric = [
_fieldTimestamp,
_fieldPositionLatitue,
_fieldPositionLongitude,
_fieldDistance,
_fieldBPM,
_fieldSpeed,
_fieldAltitude,
_fieldTemperature
];
allowedFieldCycling = [
_fieldTimestamp,
@ -150,6 +159,8 @@ class ManagerFile {
info.getDataWalking(csvData);
case (_velo):
info.getDataCycling(csvData);
case (_generic):
info.getDataGeneric(csvData);
default:
info.getDataGeneric(csvData);
}

@ -90,8 +90,9 @@ class ListActivityUtile {
String csvString = const ListToCsvConverter().convert(resultData.item2);
Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString));
/* -- Ne pas décomenter sinon web ne marche plus (Utilisé pour déboguer)
File x = await File("${await _managerFile.localPath}\\what")
.writeAsString(csvString);
.writeAsString(csvString);*/
Tuple2<bool, String> result = await api.uploadFileByte(
token,

@ -17,8 +17,8 @@ class Activity extends StatelessWidget {
.activitySelected
.isEmpty
? ScreenTypeLayout.builder(
mobile: (_) => const NoActivityView("Pas d'activité sélectionnée"),
desktop: (_) => const NoActivityView("Pas d'activité sélectionnée"),
mobile: (_) => const NoActivityView("No activities selected"),
desktop: (_) => const NoActivityView("No activities selected"),
)
: ScreenTypeLayout.builder(
mobile: (_) => const MobileActivity(),

@ -36,7 +36,7 @@ class _MobileListActivity extends State<MobileListActivity> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"List Activités",
"Activity List",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -74,7 +74,7 @@ class _MobileListActivity extends State<MobileListActivity> {
setState(() {});
},
child: Text(
"Ajouter",
"Add",
style: TextStyle(
color: TColor.gray,
fontSize: 14,
@ -93,7 +93,7 @@ class _MobileListActivity extends State<MobileListActivity> {
children: [
const SizedBox(height: 20),
Text(
"Vous n'avez pas d'activités pour le moment, veuillez en ajouter.",
"You don't have any activity at the moment, please add an activity by cliking the 'Add' button",
style: TextStyle(
color: TColor.gray,
fontSize: 11,

@ -36,7 +36,7 @@ class _WebListActivityState extends State<WebListActivity> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"List Activités",
"Activity List",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -73,7 +73,7 @@ class _WebListActivityState extends State<WebListActivity> {
}
},
child: Text(
"Ajouter",
"Add",
style: TextStyle(
color: TColor.gray,
fontSize: 14,
@ -92,7 +92,7 @@ class _WebListActivityState extends State<WebListActivity> {
children: [
const SizedBox(height: 20),
Text(
"Vous n'avez pas d'activités pour le moment, veuillez en ajouter.",
"You don't have any activity at the moment, please add an activity by cliking the 'Add' button",
style: TextStyle(
color: TColor.gray,
fontSize: 11,

@ -28,10 +28,8 @@ class _HomeViewState extends State<HomeView> {
: selectedActivitiesCount > 1
? const StatAtivities()
: ScreenTypeLayout.builder(
mobile: (_) =>
const NoActivityView("Pas d'activité sélectionnée"),
desktop: (_) =>
const NoActivityView("Pas d'activité sélectionnée"),
mobile: (_) => const NoActivityView("No activity selected"),
desktop: (_) => const NoActivityView("No activity selected"),
);
}
}

@ -68,7 +68,7 @@ class _MobileHomeView extends State<MobileHomeView> {
height: media.width * 0.05,
),
Text(
"Status d'activité",
"Activity Status",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -87,7 +87,7 @@ class _MobileHomeView extends State<MobileHomeView> {
"${avgBpm.toString()} BPM",
"Minimum",
"Maximum",
"Moyenne",
"Average",
Icons.trending_down,
Icons.trending_up,
Icons.favorite_outline),
@ -95,7 +95,7 @@ class _MobileHomeView extends State<MobileHomeView> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Rythme cardique et vitesse",
"Heart rate and speed",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -114,9 +114,9 @@ class _MobileHomeView extends State<MobileHomeView> {
"${double.parse(maxSpeed.toStringAsFixed(2))} m/s",
"${double.parse(minSpeed.toStringAsFixed(2))} m/s",
"${double.parse(avgSpeed.toStringAsFixed(2))} m/s",
"Max vitesse",
"Min vitesse",
"Moyenne vitesse",
"Max speed",
"Min speed",
"Avg speed",
Icons.trending_down,
Icons.trending_up,
Icons.trending_up),
@ -140,9 +140,9 @@ class _MobileHomeView extends State<MobileHomeView> {
"${minAltitude.toInt()} M",
"${maxAltitude.toInt()} M",
"${avgAltitude.toInt()} M",
"Altitude minimum",
"Altitude maximum",
"Altitude moyenne",
"Minimum altitude",
"Maximum altitude",
"Average altitude",
Icons.trending_down,
Icons.trending_up,
Icons.favorite_outline),

@ -49,7 +49,7 @@ class _NoActivityViewState extends State<NoActivityView> {
),
),
Text(
"Veuillez sélectionner une activité en cliquant sur la loupe ci-dessous",
"Please select an activity by clicking the magnifying glass below",
textAlign: TextAlign.center,
style: TextStyle(color: TColor.gray, fontSize: 12),
),

@ -21,17 +21,17 @@ class Prediction extends StatefulWidget {
class _PredictionState extends State<Prediction> {
List<Map<String, dynamic>> lastWorkoutArr = [
{
"name": "Temps",
"name": "Time",
"image": "assets/img/time-icon2.svg",
"value": "..",
},
{
"name": "Rythme cardiaque",
"name": "Heart rate",
"image": "assets/img/bpm2-icon.svg",
"value": "..",
},
{
"name": "Vitesse",
"name": "Speed",
"image": "assets/img/vitesse2-icon.svg",
"value": "..",
},
@ -42,7 +42,7 @@ class _PredictionState extends State<Prediction> {
}
];
final ManagerFile _managerFile = ManagerFile();
String selectedCategory = "Choisir type d'activité";
String selectedCategory = "Select an activity category";
@override
Widget build(BuildContext context) {
@ -61,11 +61,13 @@ class _PredictionState extends State<Prediction> {
if (!resultat.item1) return;
setState(() {
lastWorkoutArr[0]["value"] =
resultat.item2.timeOfActivity.toStringAsFixed(2);
lastWorkoutArr[1]["value"] = resultat.item2.bpmAvg.toStringAsFixed(2);
"${Convertisseur.secondeIntoMinute(resultat.item2.timeOfActivity).toStringAsFixed(0)} min";
lastWorkoutArr[1]["value"] =
"${resultat.item2.bpmAvg.toStringAsFixed(2)} bpm";
lastWorkoutArr[2]["value"] =
resultat.item2.vitesseAvg.toStringAsFixed(2);
lastWorkoutArr[3]["value"] = resultat.item2.distance.toStringAsFixed(2);
"${Convertisseur.msIntoKmh(resultat.item2.vitesseAvg).toStringAsFixed(1)} km/h ";
lastWorkoutArr[3]["value"] =
"${resultat.item2.distance.toStringAsFixed(2)} m";
});
}
@ -77,7 +79,7 @@ class _PredictionState extends State<Prediction> {
children: [
const SizedBox(height: 40),
Text(
"Prédiction",
"Prediction",
style: TextStyle(
color: TColor.black,
fontSize: 22,
@ -153,7 +155,7 @@ class _PredictionState extends State<Prediction> {
),
const SizedBox(height: 20),
RoundButton(
title: "Valider",
title: "Save",
onPressed: () async {
prediction();
}),

@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common_widget/container/container_stats_activities.dart';
import 'package:smartfit_app_mobile/common_widget/other/entete_home_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/convertisseur.dart';
import 'package:smartfit_app_mobile/modele/manager_selected_activity.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
@ -83,11 +84,11 @@ class _StatAtivities extends State<StatAtivities> {
double maxSpeed = context
.watch<User>()
.managerSelectedActivity
.getMaxAltitudeAllActivitySelected();
.getMaxSpeedAllActivitySelected();
double minSpeed = context
.watch<User>()
.managerSelectedActivity
.getMinAltitudeAllActivitySelected();
.getMinSpeedAllActivitySelected();
return Scaffold(
backgroundColor: TColor.white,
@ -106,7 +107,7 @@ class _StatAtivities extends State<StatAtivities> {
height: media.width * 0.05,
),
Text(
"Status d'activité",
"Activity Status",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -119,17 +120,17 @@ class _StatAtivities extends State<StatAtivities> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"$avgBpm BPM", "Moyenne Bpm", Icons.favorite),
"$avgBpm BPM", "Average bpm", Icons.favorite),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$maxBpm BPM", "Maximum Bpm", Icons.trending_up),
"$maxBpm BPM", "Maximum bpm", Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$minBpm BPM", "Minimum Bpm", Icons.trending_down)
"$minBpm BPM", "Minimum bpm", Icons.trending_down)
],
),
SizedBox(
@ -139,17 +140,23 @@ class _StatAtivities extends State<StatAtivities> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"${avgSpeed.toStringAsFixed(2)} m/s", "Moyenne vitesse", Icons.bolt),
"${Convertisseur.msIntoKmh(avgSpeed).toStringAsFixed(0)} km/h",
"Average speed",
Icons.bolt),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$maxSpeed m/s", "Maximum vitesse", Icons.trending_up),
"${Convertisseur.msIntoKmh(maxSpeed).toStringAsFixed(0)} km/h",
"Maximum speed",
Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$minSpeed m/s", "Minimum vitesse", Icons.trending_down)
"${Convertisseur.msIntoKmh(minSpeed).toStringAsFixed(0)} km/h",
"Minimum speed",
Icons.trending_down)
],
),
SizedBox(
@ -159,7 +166,7 @@ class _StatAtivities extends State<StatAtivities> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities("$avgTemperature °C",
"Moyenne Temperature", Icons.thermostat),
"Average Temperature", Icons.thermostat),
SizedBox(
width: media.width * 0.03,
),
@ -179,17 +186,19 @@ class _StatAtivities extends State<StatAtivities> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"${avgAltitude.toStringAsFixed(2)} m", "Moyenne Altitude", Icons.landscape),
"${avgAltitude.toStringAsFixed(2)} m",
"Average altitude",
Icons.landscape),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$maxAltitude m",
"Maximum Altitude", Icons.trending_up),
"Maximum altitude", Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$minAltitude m",
"Minimum Altitude", Icons.trending_down)
"Minimum altitude", Icons.trending_down)
],
),
SizedBox(
@ -199,12 +208,12 @@ class _StatAtivities extends State<StatAtivities> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities("$getTotalDistance m",
"Distance Totale", Icons.double_arrow),
"Total distance", Icons.double_arrow),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$totalSteps", "Total Pas", Icons.do_not_step_rounded),
ContainerStatsActivities("$totalSteps", "Total steps",
Icons.do_not_step_rounded),
],
),
SizedBox(
@ -214,12 +223,14 @@ class _StatAtivities extends State<StatAtivities> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"$totalTime s", "Temps Total", Icons.timer),
"${Convertisseur.secondeIntoMinute(totalTime)} min",
"Total time",
Icons.timer),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$totalCalories kCal",
"Calories Dépensées", Icons.local_fire_department),
"Burned calories", Icons.local_fire_department),
],
),
SizedBox(

@ -63,117 +63,109 @@ class _WebHomeView extends State<WebHomeView> {
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: media.width * 0.03,
),
const EnteteHomeView(),
SizedBox(
height: media.width * 0.03,
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: media.width * 0.03,
),
const EnteteHomeView(),
SizedBox(
height: media.width * 0.03,
),
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Status d'activité",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.02,
),
Row(mainAxisAlignment: MainAxisAlignment.center,
children: [
BpmByTime(media, data),
SizedBox(
width: media.width * 0.01,
),
LigneContainerStats(
"${minBpm.toString()} BPM",
"${maxBpm.toString()} BPM",
"${avgBpm.toString()} BPM",
"Minimum",
"Maximum",
"Moyenne",
Icons.trending_down,
Icons.trending_up,
Icons.favorite_outline),
]),
]),
Text(
"Activity status",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
height: media.width * 0.02,
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Rythme cardique et vitesse",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GraphBpmAndSpeedByTime(media, data),
SizedBox(
height: media.width * 0.05,
),
LigneContainerStats(
"${double.parse(maxSpeed.toStringAsFixed(2))} m/s",
"${double.parse(avgSpeed.toStringAsFixed(2))} m/s",
"${avgBpm.toString()} BPM",
"Max vitesse",
"Moy vitesse",
"Moy Bpm",
Icons.trending_up,
Icons.bolt,
Icons.favorite_outline),
SizedBox(
height: media.width * 0.05,
),
]),
]),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
BpmByTime(media, data),
SizedBox(
width: media.width * 0.01,
),
LigneContainerStats(
"${minBpm.toString()} BPM",
"${maxBpm.toString()} BPM",
"${avgBpm.toString()} BPM",
"Minimum",
"Maximum",
"Average",
Icons.trending_down,
Icons.trending_up,
Icons.favorite_outline),
]),
]),
SizedBox(
height: media.width * 0.02,
),
Text(
"Altitude",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
height: media.width * 0.05,
),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
GraphAltitudeByTime(media, data),
LigneContainerStats(
"${minAltitude.toInt()} m",
"${maxAltitude.toInt()} m",
"${avgAltitude.toInt()} m",
"Minimum",
"Maximum",
"Moyenne",
Icons.trending_down,
Icons.trending_up,
Icons.favorite_outline),
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(
"Heart rate and speed",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.03,
),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
GraphBpmAndSpeedByTime(media, data),
SizedBox(
height: media.width * 0.05,
),
LigneContainerStats(
"${double.parse(maxSpeed.toStringAsFixed(2))} m/s",
"${double.parse(avgSpeed.toStringAsFixed(2))} m/s",
"${avgBpm.toString()} BPM",
"Max speed",
"Moy speed",
"Avg bpm",
Icons.trending_up,
Icons.bolt,
Icons.favorite_outline),
SizedBox(
height: media.width * 0.05,
),
]),
]),
],
),
]),
SizedBox(
height: media.width * 0.02,
),
Text(
"Altitude",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
GraphAltitudeByTime(media, data),
LigneContainerStats(
"${minAltitude.toInt()} m",
"${maxAltitude.toInt()} m",
"${avgAltitude.toInt()} m",
"Minimum",
"Maximum",
"Average",
Icons.trending_down,
Icons.trending_up,
Icons.favorite_outline),
]),
],
),
),
),
);
}
}

@ -82,11 +82,11 @@ class _MobileLoginView extends State<MobileLoginView> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue",
"Welcome",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Se connecter",
"Log in",
style: TextStyle(
color: TColor.black,
fontSize: 20,
@ -109,7 +109,7 @@ class _MobileLoginView extends State<MobileLoginView> {
),
RoundTextField(
controller: controllerTextPassword,
hitText: "Mot de passe",
hitText: "Password",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
rigtIcon: TextButton(
@ -129,7 +129,7 @@ class _MobileLoginView extends State<MobileLoginView> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Mot de passe oublié ?",
"Password Lost ?",
style: TextStyle(
color: TColor.gray,
fontSize: 15,
@ -146,10 +146,10 @@ class _MobileLoginView extends State<MobileLoginView> {
style: TextStyle(color: TColor.red))),
const Spacer(),
RoundButton(
title: "Se connecter",
title: "Log in",
onPressed: () async {
if (!emailValidate || !passwordValidate) {
_printMsgError("Les champs renseigné ne sont pas valide");
_printMsgError("Fields are not valid!");
return;
}
Tuple2<bool, String> result =
@ -163,7 +163,7 @@ class _MobileLoginView extends State<MobileLoginView> {
if (infoUser.item1 == false) {
//print("Erreur - Impossible de récupéré les données de l'utilisateur");
_printMsgError(
"Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}");
"Can't find user data! - {$infoUser.item2}");
} else {
util.fillUser(context, infoUser.item2, result.item2);
if (!kIsWeb)
@ -175,7 +175,7 @@ class _MobileLoginView extends State<MobileLoginView> {
builder: (context) => const MainTabView()));
}
} else {
_printMsgError("Connexion refuser - ${result.item2}");
_printMsgError("Connection refused - ${result.item2}");
}
}),
SizedBox(
@ -264,14 +264,14 @@ class _MobileLoginView extends State<MobileLoginView> {
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous n'avez pas toujours pas de compte ? ",
"Don't have an account yet ?",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Créer un compte",
"Register",
style: TextStyle(
color: TColor.black,
fontSize: 14,

@ -98,11 +98,11 @@ class _MobileSignUpView extends State<MobileSignUpView> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue,",
"Welcome,",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Créer un compte",
"Register",
style: TextStyle(
color: TColor.black,
fontSize: 20,
@ -112,7 +112,7 @@ class _MobileSignUpView extends State<MobileSignUpView> {
height: media.width * 0.05,
),
RoundTextField(
hitText: "Prénom",
hitText: "Username",
icon: "assets/img/user_text.svg",
controller: controllerUsername,
),
@ -129,7 +129,7 @@ class _MobileSignUpView extends State<MobileSignUpView> {
height: media.width * 0.04,
),
RoundTextField(
hitText: "Mot de passe",
hitText: "Password",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
controller: controllerTextPassword,
@ -164,7 +164,7 @@ class _MobileSignUpView extends State<MobileSignUpView> {
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"En continuant, vous acceptez notre Politique de\nconfidentialité et nos Conditions d'utilisation.",
"I accept to not break the app",
style: TextStyle(color: TColor.gray, fontSize: 10),
),
)
@ -181,12 +181,12 @@ class _MobileSignUpView extends State<MobileSignUpView> {
height: media.width * 0.4,
),
RoundButton(
title: "Créer un compte",
title: "Register",
onPressed: () async {
if (!emailValidate ||
!passwordValidate ||
!usernameValidate) {
_printMsgError("Les champs renseigné ne sont pas valide");
_printMsgError("Fields are not valid!");
return;
}
@ -215,7 +215,7 @@ class _MobileSignUpView extends State<MobileSignUpView> {
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Ou ",
" Or ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
@ -239,14 +239,14 @@ class _MobileSignUpView extends State<MobileSignUpView> {
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous avez déjà un compte ? ",
"Already have an account ?",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Se connecter",
"Log in",
style: TextStyle(
color: TColor.black,
fontSize: 14,

@ -86,11 +86,11 @@ class _WebLoginView extends State<WebLoginView> {
height: media.width * 0.03,
),
Text(
"Bienvenue sur SmartFit",
"Welcome on SmartFit",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Se connecter",
"Log in",
style: TextStyle(
color: TColor.black,
fontSize: 20,
@ -110,7 +110,7 @@ class _WebLoginView extends State<WebLoginView> {
),
RoundTextField(
controller: controllerTextPassword,
hitText: "Mot de passe",
hitText: "Password",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
rigtIcon: TextButton(
@ -133,7 +133,7 @@ class _WebLoginView extends State<WebLoginView> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Mot de passe oublié ?",
"Password lost ?",
style: TextStyle(
color: TColor.gray,
fontSize: 15,
@ -150,11 +150,11 @@ class _WebLoginView extends State<WebLoginView> {
style: TextStyle(color: TColor.red))),
const Spacer(),
RoundButton(
title: "Se connecter",
title: "Log in",
onPressed: () async {
// TODO: utiliser la vrai validation
if (!emailValidate || !passwordValidate) {
_printMsgError("Les champs renseigné ne sont pas valide");
_printMsgError("Fields are not valid!");
return;
}
Tuple2<bool, String> result =
@ -168,7 +168,7 @@ class _WebLoginView extends State<WebLoginView> {
if (infoUser.item1 == false) {
//print("Erreur - Impossible de récupéré les données de l'utilisateur");
_printMsgError(
"Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}");
"Can't find user data - {$infoUser.item2}");
} else {
util.fillUser(context, infoUser.item2, result.item2);
if (!kIsWeb)
@ -180,7 +180,7 @@ class _WebLoginView extends State<WebLoginView> {
builder: (context) => const MainTabView()));
}
} else {
_printMsgError("Connexion refuser - ${result.item2}");
_printMsgError("Connection refused - ${result.item2}");
}
}),
SizedBox(
@ -197,14 +197,14 @@ class _WebLoginView extends State<WebLoginView> {
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous n'avez pas toujours pas de compte ? ",
"Don't have an account yet ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Créer un compte",
"Register",
style: TextStyle(
color: TColor.black,
fontSize: 14,

@ -100,11 +100,11 @@ class _WebSignUpView extends State<WebSignUpView> {
height: media.width * 0.04,
),
Text(
"Bienvenue,",
"Welcome,",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Créer un compte",
"Register",
style: TextStyle(
color: TColor.black,
fontSize: 20,
@ -114,7 +114,7 @@ class _WebSignUpView extends State<WebSignUpView> {
height: media.width * 0.05,
),
RoundTextField(
hitText: "Prénom",
hitText: "Username",
icon: "assets/img/user_text.svg",
controller: controllerUsername,
),
@ -131,7 +131,7 @@ class _WebSignUpView extends State<WebSignUpView> {
height: media.width * 0.04,
),
RoundTextField(
hitText: "Mot de passe",
hitText: "Password",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
controller: controllerTextPassword,
@ -166,7 +166,7 @@ class _WebSignUpView extends State<WebSignUpView> {
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"En continuant, vous acceptez notre Politique de\nconfidentialité et nos Conditions d'utilisation.",
"Please don't break the app",
style: TextStyle(color: TColor.gray, fontSize: 10),
),
)
@ -180,12 +180,12 @@ class _WebSignUpView extends State<WebSignUpView> {
height: media.width * 0.05,
),
RoundButton(
title: "Créer un compte",
title: "Register",
onPressed: () async {
if (!emailValidate ||
!passwordValidate ||
!usernameValidate) {
_printMsgError("Les champs renseigné ne sont pas valide");
_printMsgError("Fields are not valid!");
return;
}
Tuple2<bool, String> result = await util.createUser(
@ -215,14 +215,14 @@ class _WebSignUpView extends State<WebSignUpView> {
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous avez déjà un compte ? ",
"Already have an account ?",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Se connecter",
"Log in",
style: TextStyle(
color: TColor.black,
fontSize: 14,

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

@ -21,16 +21,16 @@ class _MyMapState extends State<MyMap> {
if (listSelected.isEmpty) {
return ScreenTypeLayout.builder(
mobile: (_) => const NoActivityView("Pas d'activité sélectionnée"),
desktop: (_) => const NoActivityView("Pas d'activité sélectionnée"),
mobile: (_) => const NoActivityView("No activity selected"),
desktop: (_) => const NoActivityView("No activity selected"),
);
}
if (listSelected.length > 1) {
return ScreenTypeLayout.builder(
mobile: (_) => const NoActivityView(
"Une seule activité doit être sélectionnée"),
desktop: (_) => const NoActivityView(
"Une seule activité doit être sélectionnée"),
mobile: (_) =>
const NoActivityView("Only one activity must be selected"),
desktop: (_) =>
const NoActivityView("Only one activity must be selected"),
);
}
return ScreenTypeLayout.builder(

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

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

@ -27,21 +27,21 @@ class _OnBoardingViewState extends State<OnBoardingView> {
List pageArr = [
{
"title": "Atteignez vos objectifs",
"title": "Achieve your goals",
"subtitle":
"Ne vous inquiétez pas si vous avez du mal à déterminer vos objectifs. Grâce à l'analyse concrète de vos performances, nous vous aiderons à les atteindre.",
"Don't worry if you have trouble determining your goals. Thanks to the concrete analysis of your performances, we will help you achieve them.",
"image": "assets/img/on_1.svg"
},
{
"title": "Persévérez",
"subtitle":
"Continuez à persévérer pour atteindre vos objectifs. La douleur n'est que temporaire. Si vous abandonnez maintenant, vous souffrirez éternellement.",
"Continue to persevere to achieve your goals. The pain is only temporary. If you give up now, you will suffer forever.",
"image": "assets/img/on_2.svg"
},
{
"title": "Laissez-nous piloter, mettez simplement votre Suunto",
"title": "Let us pilot, just put on your Suunto",
"subtitle":
"Détendez-vous, nous prenons les commandes en analysant performances et statistiques pour vous aider à atteindre vos objectifs.",
"Relax, we take charge by analyzing performance and statistics to help you achieve your goals.",
"image": "assets/img/on_3.svg"
},
];

@ -41,7 +41,7 @@ class _StartedViewState extends State<StartedView> {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: RoundButton(
title: "Commencer",
title: "Start",
type: isChangeColor
? RoundButtonType.textGradient
: RoundButtonType.bgGradient,

@ -112,7 +112,7 @@ class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: logOff,
child: const Text('Déconnexion',
child: const Text('Log out',
style: TextStyle(color: Colors.black)),
),
const SizedBox(
@ -124,7 +124,7 @@ class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: deleteUser,
child: const Text('Supprimer son compte',
child: const Text('Delete your account',
style: TextStyle(color: Colors.black)),
),
],

@ -35,7 +35,7 @@ class ContactUsView extends StatelessWidget {
),
),
title: Text(
"Nous Contacter",
"Contact us",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -50,17 +50,16 @@ class ContactUsView extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(height: media.width * 0.02),
const Text(
"Vous pouvez nous contacter pour toute question, suggestion ou problème concernant notre application SmartFit.",
"You can contact us with any questions, suggestions or issues regarding our SmartFit app.",
style: TextStyle(
fontSize: 16,
),
),
SizedBox(height: media.width * 0.05),
const Text(
"Adresse e-mail",
"Email address",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
@ -74,7 +73,7 @@ class ContactUsView extends StatelessWidget {
),
SizedBox(height: media.width * 0.02),
const Text(
"Téléphone",
"Phone",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
@ -88,7 +87,7 @@ class ContactUsView extends StatelessWidget {
),
SizedBox(height: media.width * 0.02),
const Text(
"Adresse",
"Address",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
@ -102,14 +101,14 @@ class ContactUsView extends StatelessWidget {
),
SizedBox(height: media.width * 0.02),
const Text(
"Heures de bureau",
"Schedules",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const Text(
"Lundi - Vendredi : 9h00 - 18h00",
"Monday - Friday : 9h00 - 18h00",
style: TextStyle(
fontSize: 16,
),

@ -52,7 +52,7 @@ class _MobileChangeEmailViewState extends State<MobileChangeEmailView> {
),
),
title: Text(
"Changer son e-mail",
"Change your email",
style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
),
@ -70,7 +70,7 @@ class _MobileChangeEmailViewState extends State<MobileChangeEmailView> {
Row(
children: [
Text(
"Ancien e-mail : ",
"Current email : ",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -95,7 +95,7 @@ class _MobileChangeEmailViewState extends State<MobileChangeEmailView> {
child: Column(
children: [
RoundTextField(
hitText: "Nouveau e-mail",
hitText: "New email",
icon: "assets/img/user_text.svg",
keyboardType: TextInputType.text,
controller: controllerTextEmail,
@ -110,7 +110,7 @@ class _MobileChangeEmailViewState extends State<MobileChangeEmailView> {
height: media.width * 0.01,
),
RoundButton(
title: "Confirmer",
title: "Confirm",
onPressed: () async {
bool res = await api.updateUserInfo(
'email',

@ -56,7 +56,7 @@ class _MobileChangePasswordViewState extends State<MobileChangePasswordView> {
),
),
title: Text(
"Changer son Mot de passe",
"Change your password",
style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
),
@ -80,7 +80,7 @@ class _MobileChangePasswordViewState extends State<MobileChangePasswordView> {
children: [
SizedBox(height: media.width * 0.05),
RoundTextField(
hitText: "Ancien mot de passe",
hitText: "Current password",
obscureText: true,
icon: "assets/img/lock.svg",
keyboardType: TextInputType.text,
@ -89,20 +89,20 @@ class _MobileChangePasswordViewState extends State<MobileChangePasswordView> {
SizedBox(height: media.width * 0.07),
RoundTextField(
controller: controllerNewPasswd,
hitText: "Nouveau mot de passe",
hitText: "New password",
icon: "assets/img/lock.svg",
obscureText: true,
),
SizedBox(height: media.width * 0.07),
RoundTextField(
controller: controllerNewPasswd2,
hitText: "Confirmer nouveau mot de passe",
hitText: "Confirm new password",
icon: "assets/img/lock.svg",
obscureText: true,
),
SizedBox(height: media.width * 0.07),
RoundButton(
title: "Confirmer",
title: "Confirm",
onPressed: () async {
Tuple2<bool, String> res = await api.login(
controllerActualPasswd.text,

@ -53,7 +53,7 @@ class _MobileChangeUsernameViewState extends State<MobileChangeUsernameView> {
),
),
title: Text(
"Changer son pseudo",
"Change your username",
style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
),
@ -71,7 +71,7 @@ class _MobileChangeUsernameViewState extends State<MobileChangeUsernameView> {
Row(
children: [
Text(
"Ancien pseudo : ",
"Current username: ",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -96,7 +96,7 @@ class _MobileChangeUsernameViewState extends State<MobileChangeUsernameView> {
child: Column(
children: [
RoundTextField(
hitText: "Nouveau pseudo",
hitText: "New username",
icon: "assets/img/user_text.svg",
keyboardType: TextInputType.text,
controller: controllerTextUsername,
@ -109,7 +109,7 @@ class _MobileChangeUsernameViewState extends State<MobileChangeUsernameView> {
TextStyle(color: infoManager.messageColor))),
SizedBox(height: media.width * 0.02),
RoundButton(
title: "Confirmer",
title: "Confirm",
onPressed: () async {
bool res = await api.updateUserInfo(
'username',

@ -14,28 +14,24 @@ class _MobileProfileView extends State<MobileProfileView> {
List accountArr = [
{
"image": "assets/img/p_personal.png",
"name": "Changer son pseudo",
"name": "Change your username",
"tag": "1"
},
{
"image": "assets/img/p_personal.png",
"name": "Changer son email",
"name": "Change your email",
"tag": "3"
},
{
"image": "assets/img/p_personal.png",
"name": "Changer son mot de passe",
"name": "Change your password",
"tag": "2"
},
];
List otherArr = [
{"image": "assets/img/p_contact.png", "name": "Nous contacter", "tag": "5"},
{
"image": "assets/img/p_privacy.png",
"name": "Politique de confidentialité",
"tag": "6"
},
{"image": "assets/img/p_contact.png", "name": "Contact us", "tag": "5"},
{"image": "assets/img/p_privacy.png", "name": "Privacy policy", "tag": "6"},
];
@override
Widget build(BuildContext context) {

@ -35,7 +35,7 @@ class PrivacyPolicyView extends StatelessWidget {
),
),
title: Text(
"Politique de confidentialité",
"Privacy policy",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -51,7 +51,7 @@ class PrivacyPolicyView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
"Politique de confidentialité de SmartFit",
"SmartFit privacy policy",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
@ -59,14 +59,14 @@ class PrivacyPolicyView extends StatelessWidget {
),
SizedBox(height: media.width * 0.02),
const Text(
"Cette Politique de confidentialité explique comment SmartFit collecte, utilise, protège et partage vos informations lorsque vous utilisez notre application mobile SmartFit.",
"This Privacy Policy explains how SmartFit collects, uses, protects and shares your information when you use our SmartFit mobile application.",
style: TextStyle(
fontSize: 16,
),
),
SizedBox(height: media.width * 0.05),
const Text(
"Collecte et Utilisation des Informations",
"Collect and usage of your data",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
@ -77,7 +77,7 @@ class PrivacyPolicyView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"SmartFit recueille des données uniquement dans le but d'analyser et d'afficher des informations relatives à vos activités physiques à partir des données collectées par votre montre connectée. Ces informations peuvent inclure, sans toutefois s'y limiter :",
"SmartFit collects data solely for the purpose of analyzing and displaying information about your physical activities based on data collected by your smartwatch. This information may include, but is not limited to:",
style: TextStyle(
fontSize: 16,
),
@ -87,31 +87,31 @@ class PrivacyPolicyView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"• Données d'activité physique (comme la fréquence cardiaque, le nombre de pas, la distance parcourue, etc.)",
" Physical activity data (such as heart rate, number of steps, distance traveled, etc.",
style: TextStyle(
fontSize: 16,
),
),
Text(
"Données sur les habitudes de sommeil",
"Sleep data",
style: TextStyle(
fontSize: 16,
),
),
Text(
"Informations de localisation (si l'option est activée par l'utilisateur)",
"GPS data",
style: TextStyle(
fontSize: 16,
),
),
Text(
"Préférences de l'utilisateur concernant les paramètres de l'application",
"Application parameters",
style: TextStyle(
fontSize: 16,
),
),
Text(
"Ces informations sont utilisées pour générer des graphiques, des statistiques et des recommandations personnalisées afin de vous aider dans vos objectifs de remise en forme.",
"This information is used to generate graphs, statistics and personalized recommendations to help you with your fitness goals.",
style: TextStyle(
fontSize: 16,
),
@ -122,7 +122,7 @@ class PrivacyPolicyView extends StatelessWidget {
),
SizedBox(height: media.width * 0.05),
const Text(
"Protection des Informations",
"Information protection",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,

@ -52,7 +52,7 @@ class _WebChangeEmailViewState extends State<WebChangeEmailView> {
),
),
title: Text(
"Changer son email",
"Change you email",
style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
),
@ -70,7 +70,7 @@ class _WebChangeEmailViewState extends State<WebChangeEmailView> {
Row(
children: [
Text(
"Email actuel : ",
"Current email: ",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -95,7 +95,7 @@ class _WebChangeEmailViewState extends State<WebChangeEmailView> {
child: Column(
children: [
RoundTextField(
hitText: "Nouveau email",
hitText: "New email",
icon: "assets/img/user_text.svg",
keyboardType: TextInputType.text,
controller: controllerTextEmail,
@ -108,7 +108,7 @@ class _WebChangeEmailViewState extends State<WebChangeEmailView> {
TextStyle(color: infoManager.messageColor))),
SizedBox(height: media.width * 0.03),
RoundButton(
title: "Confirmer",
title: "Confirm",
onPressed: () async {
bool res = await apiWrapper.updateUserInfo(
'email',

@ -55,7 +55,7 @@ class _WebChangePasswordViewState extends State<WebChangePasswordView> {
),
),
title: Text(
"Changer son Mot de passe",
"Change password",
style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
),
@ -78,7 +78,7 @@ class _WebChangePasswordViewState extends State<WebChangePasswordView> {
child: Column(
children: [
RoundTextField(
hitText: "Ancien mot de passe",
hitText: "Current password",
obscureText: true,
icon: "assets/img/lock.svg",
keyboardType: TextInputType.text,
@ -87,14 +87,14 @@ class _WebChangePasswordViewState extends State<WebChangePasswordView> {
SizedBox(height: media.width * 0.02),
RoundTextField(
controller: controllerNewPasswd,
hitText: "Nouveau mot de passe",
hitText: "New password",
icon: "assets/img/lock.svg",
obscureText: true,
),
SizedBox(height: media.width * 0.02),
RoundTextField(
controller: controllerNewPasswd2,
hitText: "Confirmer nouveau mot de passe",
hitText: "Confirm new password",
icon: "assets/img/lock.svg",
obscureText: true,
),
@ -105,7 +105,7 @@ class _WebChangePasswordViewState extends State<WebChangePasswordView> {
TextStyle(color: infoManager.messageColor))),
SizedBox(height: media.width * 0.04),
RoundButton(
title: "Confirmer",
title: "Confirm",
onPressed: () async {
Tuple2<bool, String> res = await api.login(
controllerActualPasswd.text,

@ -52,7 +52,7 @@ class _WebChangeUsernameViewState extends State<WebChangeUsernameView> {
),
),
title: Text(
"Changer son pseudo",
"Change your username",
style: TextStyle(
color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700),
),
@ -70,7 +70,7 @@ class _WebChangeUsernameViewState extends State<WebChangeUsernameView> {
Row(
children: [
Text(
"Ancien pseudo : ",
"Current username: ",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -95,7 +95,7 @@ class _WebChangeUsernameViewState extends State<WebChangeUsernameView> {
child: Column(
children: [
RoundTextField(
hitText: "Nouveau pseudo",
hitText: "New username",
icon: "assets/img/user_text.svg",
keyboardType: TextInputType.text,
controller: controllerTextUsername,
@ -110,7 +110,7 @@ class _WebChangeUsernameViewState extends State<WebChangeUsernameView> {
TextStyle(color: infoManager.messageColor))),
SizedBox(height: media.width * 0.04),
RoundButton(
title: "Confirmer",
title: "Confirm",
onPressed: () async {
bool res = await api.updateUserInfo(
'username',

@ -14,32 +14,24 @@ class _WebProfileView extends State<WebProfileView> {
List accountArr = [
{
"image": "assets/img/p_personal.png",
"name": "Changer son pseudo ",
"name": "Change your username",
"tag": "1"
},
{
"image": "assets/img/p_personal.png",
"name": "Changer son email ",
"name": "Change your email",
"tag": "3"
},
{
"image": "assets/img/p_personal.png",
"name": "Changer son mot de passe ",
"name": "Changer your password",
"tag": "2"
},
];
List otherArr = [
{
"image": "assets/img/p_contact.png",
"name": "Nous contacter !!",
"tag": "5"
},
{
"image": "assets/img/p_privacy.png",
"name": "Politique de confidentialité",
"tag": "6"
},
{"image": "assets/img/p_contact.png", "name": "Contact us !", "tag": "5"},
{"image": "assets/img/p_privacy.png", "name": "Privacy policy", "tag": "6"},
];
@override
Widget build(BuildContext context) {

@ -48,7 +48,7 @@ class _VolumesViews extends State<VolumesView> {
height: media.width * 0.05,
),
Text(
"Derniere semaine : ${date.day}/${date.month}/${date.year} - ${date.subtract(const Duration(days: 7)).day}/${date.subtract(const Duration(days: 7)).month}/${date.subtract(const Duration(days: 7)).year}",
"Last week: ${date.day}/${date.month}/${date.year} - ${date.subtract(const Duration(days: 7)).day}/${date.subtract(const Duration(days: 7)).month}/${date.subtract(const Duration(days: 7)).year}",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -62,7 +62,7 @@ class _VolumesViews extends State<VolumesView> {
height: media.width * 0.03,
),
Text(
"Dernier Mois : ${date.day}/${date.month}/${date.year} - ${date.subtract(const Duration(days: 30)).day}/${date.subtract(const Duration(days: 30)).month}/${date.subtract(const Duration(days: 30)).year}",
"Last month: ${date.day}/${date.month}/${date.year} - ${date.subtract(const Duration(days: 30)).day}/${date.subtract(const Duration(days: 30)).month}/${date.subtract(const Duration(days: 30)).year}",
style: TextStyle(
color: TColor.black,
fontSize: 16,
@ -73,7 +73,7 @@ class _VolumesViews extends State<VolumesView> {
height: media.width * 0.03,
),
Text(
"Dernière année : ${date.day}/${date.month}/${date.year} - ${date.subtract(const Duration(days: 366)).day}/${date.subtract(const Duration(days: 366)).month}/${date.subtract(const Duration(days: 366)).year}",
"Last year: ${date.day}/${date.month}/${date.year} - ${date.subtract(const Duration(days: 366)).day}/${date.subtract(const Duration(days: 366)).month}/${date.subtract(const Duration(days: 366)).year}",
style: TextStyle(
color: TColor.black,
fontSize: 16,

Loading…
Cancel
Save