Merge pull request 'Enzo' (#2) from Enzo into master
continuous-integration/drone/push Build is failing Details

Reviewed-on: #2
profile
remrem 2 years ago
commit a397d5e0c8

@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
revision: "6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e"
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06"
channel: "stable"
project_type: app
@ -13,26 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
- platform: android
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
- platform: ios
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
- platform: linux
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
- platform: macos
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
- platform: web
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
- platform: windows
create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
# User provided section

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
@ -12,7 +11,15 @@ class RoundTextField extends StatelessWidget {
final Widget? rigtIcon;
final bool obscureText;
final EdgeInsets? margin;
const RoundTextField({super.key, required this.hitText, required this.icon, this.controller, this.margin, this.keyboardType, this.obscureText = false , this.rigtIcon });
const RoundTextField(
{super.key,
required this.hitText,
required this.icon,
this.controller,
this.margin,
this.keyboardType,
this.obscureText = false,
this.rigtIcon});
@override
Widget build(BuildContext context) {
@ -36,7 +43,7 @@ class RoundTextField extends StatelessWidget {
width: 20,
height: 20,
child: SvgPicture.asset(
icon,
icon,
width: 20,
height: 20,
fit: BoxFit.contain,
@ -45,4 +52,4 @@ class RoundTextField extends StatelessWidget {
),
);
}
}
}

@ -1,8 +1,8 @@
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/Modele/activity.dart';
import 'package:smartfit_app_mobile/Modele/user.dart';
import 'package:smartfit_app_mobile/View/activity/activity.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/view/activity/activity.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:flutter/material.dart';
import 'package:simple_animation_progress_bar/simple_animation_progress_bar.dart';
@ -11,7 +11,12 @@ class WorkoutRow extends StatelessWidget {
final Map wObj;
final VoidCallback onDelete;
final VoidCallback onClick;
const WorkoutRow({Key? key, required this.wObj, required this.onDelete, required this.onClick}) : super(key: key);
const WorkoutRow(
{Key? key,
required this.wObj,
required this.onDelete,
required this.onClick})
: super(key: key);
@override
Widget build(BuildContext context) {

@ -1,7 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'package:smartfit_app_mobile/Modele/Api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:http/http.dart' as http;
import 'package:tuple/tuple.dart';
@ -101,12 +101,10 @@ class RequestApi extends IDataStrategy {
@override
Future<Tuple2<bool, String>> postUser(
String email, String hash, String username) async {
var body = {"email": email, "hash": hash, "username": username};
var header = {"Content-Type": "application/json"};
final response = await http.post(Uri.parse('$urlApi/user'),
body: <String, String>{
"email": email,
"hash": hash,
"username": username
});
headers: header, body: jsonEncode(body));
if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(response.body);
@ -157,7 +155,10 @@ class RequestApi extends IDataStrategy {
Future<Tuple2> modifAttribut(
String token, String nameAttribut, String newValue) async {
final response = await http.put(Uri.parse('$urlApi/user/$nameAttribut'),
headers: <String, String>{'Authorization': token},
headers: <String, String>{
'Authorization': token,
"Content-Type": "application/json"
},
body: jsonEncode(<String, String>{nameAttribut: newValue}));
if (response.statusCode == 200) {
@ -176,15 +177,23 @@ class RequestApi extends IDataStrategy {
@override
Future<Tuple2<bool, String>> uploadFile(String token, File file) async {
String filename = file.path.split('/').last;
String categoryActivity = filename.split("_").first.toLowerCase();
String dateActivity = filename.split("_")[1].split("T").first;
final uri = Uri.parse('$urlApi/user/files');
Map<String, String> headers = {'Authorization': token};
var request = http.MultipartRequest('POST', uri);
final httpImage = http.MultipartFile.fromBytes(
'file', await file.readAsBytes(),
filename: file.path.split('/').last);
'file',
await file.readAsBytes(),
filename: filename,
);
request.files.add(httpImage);
request.headers.addAll(headers);
request.fields["SmartFit_Category"] = categoryActivity;
request.fields["SmartFit_Date"] = dateActivity;
final response = await request.send();

@ -1,21 +1,17 @@
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/Modele/activity.dart';
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/Modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/view/activity/list_activity.dart';
class User extends ChangeNotifier {
String? username;
String? email;
String? token;
List<ActivityOfUser> listActivity = [];
String username = "VOID";
String email = "VOID";
String token = "VOID";
List<ActivityOfUser> listActivity = List.empty();
void addActivity(ActivityOfUser activity) {
listActivity.add(activity);
notifyListeners();
}
}
void removeActivity(ActivityOfUser activity) {
listActivity.remove(activity);

@ -0,0 +1,37 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:tuple/tuple.dart';
class Login {
final IDataStrategy api = RequestApi();
Future<Tuple2<bool, String>> checkLoginAndPassword(
String email, String password) async {
Tuple2<bool, String> result = await api.connexion(
email, sha256.convert(utf8.encode(password)).toString());
return result;
}
Future<Tuple2<bool, Map<dynamic, dynamic>>> getUserInfo(String token) async {
Tuple2 result = await api.getInfoUser(token);
if (result.item1 == false) {
return const Tuple2(false, <String, String>{"Empty": "Empty"});
}
return Tuple2(true, result.item2);
}
void fillUser(BuildContext context, Map<String, dynamic> map, String token) {
print(map);
context.read<User>().email = map["email"];
context.read<User>().username = map["username"];
context.read<User>().token = token;
context.read<User>().listActivity = List.empty(growable: true);
}
}

@ -0,0 +1,16 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:tuple/tuple.dart';
class SignUp {
final IDataStrategy api = RequestApi();
Future<Tuple2<bool, String>> createUser(
String email, String username, String password) async {
return await api.postUser(
email, sha256.convert(utf8.encode(password)).toString(), username);
}
}

@ -1,7 +1,6 @@
import 'package:smartfit_app_mobile/common_widget/steps.dart';
import 'package:smartfit_app_mobile/common_widget/graph.dart';
import 'package:smartfit_app_mobile/common_widget/info.dart' hide Stats;
import 'package:smartfit_app_mobile/common_widget/stats.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/view/home/mobile/mobile_Activity_view.dart';
import 'package:smartfit_app_mobile/view/home/web/web_Activity_view.dart';
import 'package:flutter/material.dart';
class Activity extends StatelessWidget {
@ -9,19 +8,9 @@ class Activity extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: const [
Divider(height: 80),
Steps(),
Graph(),
Info(),
Divider(height: 30),
Stats(),
SizedBox(height: 30),
],
),
return ScreenTypeLayout.builder(
mobile: (_) => const MobileActivity(),
desktop: (_) => const WebActivity(),
);
}
}

@ -195,7 +195,7 @@ class _ListActivityState extends State<ListActivity> {
)
],
),
Provider.of<User>(context, listen: true).listActivity.isEmpty
Provider.of<User>(context, listen: true).listActivity!.isEmpty
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -215,12 +215,12 @@ class _ListActivityState extends State<ListActivity> {
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: Provider.of<User>(context, listen: true)
.listActivity
.listActivity!
.length,
itemBuilder: (context, index) {
var activityObj =
Provider.of<User>(context, listen: true)
.listActivity[index] as ActivityOfUser;
.listActivity![index] as ActivityOfUser;
var activityMap = activityObj.toMap();
return InkWell(
onTap: () {

File diff suppressed because it is too large Load Diff

@ -0,0 +1,27 @@
import 'package:smartfit_app_mobile/common_widget/steps.dart';
import 'package:smartfit_app_mobile/common_widget/graph.dart';
import 'package:smartfit_app_mobile/common_widget/info.dart' hide Stats;
import 'package:smartfit_app_mobile/common_widget/stats.dart';
import 'package:flutter/material.dart';
class MobileActivity extends StatelessWidget {
const MobileActivity({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: const [
Divider(height: 80),
Steps(),
Graph(),
Info(),
Divider(height: 30),
Stats(),
SizedBox(height: 30),
],
),
);
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,27 @@
import 'package:smartfit_app_mobile/common_widget/steps.dart';
import 'package:smartfit_app_mobile/common_widget/graph.dart';
import 'package:smartfit_app_mobile/common_widget/info.dart' hide Stats;
import 'package:smartfit_app_mobile/common_widget/stats.dart';
import 'package:flutter/material.dart';
class WebActivity extends StatelessWidget {
const WebActivity({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: const [
Divider(height: 80),
Steps(),
Graph(),
Info(),
Divider(height: 30),
Stats(),
SizedBox(height: 30),
],
),
);
}
}

File diff suppressed because it is too large Load Diff

@ -1,17 +1,7 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.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/user.dart';
import 'package:smartfit_app_mobile/View/activity/list_activity.dart';
import 'package:smartfit_app_mobile/View/page_test.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/round_text_field.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/view/login/mobile/android_login_view.dart';
import 'package:smartfit_app_mobile/view/login/web/web_login_view.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
class LoginView extends StatefulWidget {
const LoginView({super.key});
@ -21,258 +11,10 @@ class LoginView extends StatefulWidget {
}
class _LoginViewState extends State<LoginView> {
bool _obscureText = true;
String _msgError = "";
bool _errorLogin = false;
IDataStrategy api = RequestApi();
final controllerTextEmail = TextEditingController();
final controllerTextPassword = TextEditingController();
Future<Tuple2<bool, String>> checkLoginAndPassword() async {
Tuple2<bool, String> result = await api.connexion(controllerTextEmail.text,
sha256.convert(utf8.encode(controllerTextPassword.text)).toString());
return result;
}
Future<Tuple2<bool, Map<dynamic, dynamic>>> getUserInfo(String token) async {
Tuple2 result = await api.getInfoUser(token);
if (result.item1 == false) {
return const Tuple2(false, <String, String>{"Empty": "Empty"});
}
return Tuple2(true, result.item2);
}
void fillUser(BuildContext context, Map<String, dynamic> map, String token) {
context.read<User>().email = map["email"];
context.read<User>().username = map["username"];
context.read<User>().token = token;
context.read<User>().listActivity = List.empty(growable: true);
print(context.read<User>());
}
// Toggles the password show status
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Container(
height: media.height * 0.9,
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue,",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Se connecter",
style: TextStyle(
color: TColor.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Email",
icon: "assets/img/email.svg",
keyboardType: TextInputType.emailAddress,
controller: controllerTextEmail,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
controller: controllerTextPassword,
hitText: "Mot de passe",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
rigtIcon: TextButton(
onPressed: _toggle,
child: Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: SvgPicture.asset(
"assets/img/show_password.svg",
width: 20,
height: 20,
fit: BoxFit.contain,
))),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Mot de passe oublié ?",
style: TextStyle(
color: TColor.gray,
fontSize: 15,
decoration: TextDecoration.underline),
),
],
),
Visibility(
visible: _errorLogin,
child: Text("Error - $_msgError",
style: TextStyle(color: TColor.red))),
const Spacer(),
RoundButton(
title: "Se connecter",
onPressed: () async {
Tuple2<bool, String> result =
await checkLoginAndPassword();
if (result.item1 == true) {
Tuple2 infoUser = await getUserInfo(result.item2);
if (infoUser.item1 == false) {
//print("Erreur - Impossible de récupéré les données de l'utilisateur");
setState(() {
_msgError =
"Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}";
_errorLogin = true;
});
} else {
fillUser(context, infoUser.item2, result.item2);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ListActivity()));
}
} else {
setState(() {
_msgError = "Connexion refuser - ${result.item2}";
_errorLogin = true;
});
}
}),
SizedBox(
height: media.width * 0.04,
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Or ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
],
),
SizedBox(
height: media.width * 0.04,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous n'avez pas toujours pas de compte ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Créer un compte",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w700),
)
],
),
),
SizedBox(
height: media.width * 0.04,
),
],
),
),
),
),
);
return ScreenTypeLayout.builder(
mobile: (_) => const MobileLoginView(),
desktop: (_) => const WebLoginView());
}
}

@ -0,0 +1,291 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/modele/utile/login_user.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/round_text_field.dart';
import 'package:tuple/tuple.dart';
class MobileLoginView extends StatefulWidget {
const MobileLoginView({super.key});
@override
State<MobileLoginView> createState() => _MobileLoginView();
}
class _MobileLoginView extends State<MobileLoginView> {
final Login util = Login();
bool _obscureText = true;
bool _errorLogin = false;
String _msgError = "";
bool emailValidate = false;
bool passwordValidate = false;
final controllerTextEmail = TextEditingController();
final controllerTextPassword = TextEditingController();
@override
void initState() {
super.initState();
// Start listening to changes.
controllerTextEmail.addListener(checkEmail);
controllerTextPassword.addListener(checkPassword);
}
// Toggles the password show status
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
void _printMsgError(String msgError) {
setState(() {
_msgError = msgError;
_errorLogin = true;
});
}
void checkEmail() {
if (!controllerTextEmail.text.contains("@") &&
!(controllerTextEmail.text.length > 6)) {
emailValidate = false;
// Faire un affichage
return;
} // Enlever l'affichage
emailValidate = true;
}
void checkPassword() {
if (!(controllerTextEmail.text.length >= 4)) {
passwordValidate = false;
//Faire un affichage
return;
} // Enlever l'affichage
passwordValidate = true;
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Container(
height: media.height * 0.9,
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Se connecter",
style: TextStyle(
color: TColor.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Email",
icon: "assets/img/email.svg",
keyboardType: TextInputType.emailAddress,
controller: controllerTextEmail,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
controller: controllerTextPassword,
hitText: "Mot de passe",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
rigtIcon: TextButton(
onPressed: _toggle,
child: Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: SvgPicture.asset(
"assets/img/show_password.svg",
width: 20,
height: 20,
fit: BoxFit.contain,
))),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Mot de passe oublié ?",
style: TextStyle(
color: TColor.gray,
fontSize: 15,
decoration: TextDecoration.underline),
),
],
),
SizedBox(
height: media.width * 0.04,
),
Visibility(
visible: _errorLogin,
child: Text("Error - $_msgError",
style: TextStyle(color: TColor.red))),
const Spacer(),
RoundButton(
title: "Se connecter",
onPressed: () async {
if (!emailValidate || !passwordValidate) {
_printMsgError(
"Les champs renseigné ne sont pas valide");
return;
}
Tuple2<bool, String> result =
await util.checkLoginAndPassword(
controllerTextEmail.text,
controllerTextPassword.text);
if (result.item1 == true) {
Tuple2 infoUser = await util.getUserInfo(result.item2);
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}");
} else {
util.fillUser(context, infoUser.item2, result.item2);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MainTabView()));
}
} else {
_printMsgError("Connexion refuser - ${result.item2}");
}
}),
SizedBox(
height: media.width * 0.04,
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Or ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
],
),
SizedBox(
height: media.width * 0.04,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous n'avez pas toujours pas de compte ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Créer un compte",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w700),
)
],
),
),
SizedBox(
height: media.width * 0.04,
),
],
),
),
),
),
);
}
}

@ -0,0 +1,323 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/modele/utile/signup_user.dart';
import 'package:smartfit_app_mobile/view/login/login_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/round_text_field.dart';
import 'package:tuple/tuple.dart';
class MobileSignUpView extends StatefulWidget {
const MobileSignUpView({super.key});
@override
State<MobileSignUpView> createState() => _MobileSignUpView();
}
class _MobileSignUpView extends State<MobileSignUpView> {
final SignUp util = SignUp();
bool _obscureText = true;
bool _errorCreateUser = false;
bool _isCheck = false;
String _msgError = "";
bool emailValidate = false;
bool passwordValidate = false;
bool usernameValidate = false;
final controllerTextEmail = TextEditingController();
final controllerUsername = TextEditingController();
final controllerTextPassword = TextEditingController();
@override
void initState() {
super.initState();
// Start listening to changes.
controllerTextEmail.addListener(checkEmail);
controllerTextPassword.addListener(checkPassword);
controllerUsername.addListener(checkUsername);
}
// Toggles the password show status
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
void _printMsgError(String msgError) {
setState(() {
_msgError = msgError;
_errorCreateUser = true;
});
}
void _check() {
setState(() {
_isCheck = !_isCheck;
});
}
void checkEmail() {
if (!controllerTextEmail.text.contains("@") &&
!(controllerTextEmail.text.length > 6)) {
emailValidate = false;
// Faire un affichage
return;
} // Enlever l'affichage
emailValidate = true;
}
void checkPassword() {
if (!(controllerTextEmail.text.length >= 4)) {
passwordValidate = false;
//Faire un affichage
return;
} // Enlever l'affichage
passwordValidate = true;
}
void checkUsername() {
if (controllerUsername.text.isEmpty) {
usernameValidate = false;
return;
}
usernameValidate = true;
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue,",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Créer un compte",
style: TextStyle(
color: TColor.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
),
RoundTextField(
hitText: "Prénom",
icon: "assets/img/user_text.svg",
controller: controllerUsername,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Email",
icon: "assets/img/email.svg",
keyboardType: TextInputType.emailAddress,
controller: controllerTextEmail,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Mot de passe",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
controller: controllerTextPassword,
rigtIcon: TextButton(
onPressed: _toggle,
child: Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: SvgPicture.asset(
"assets/img/show_password.svg",
width: 20,
height: 20,
fit: BoxFit.contain,
))),
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
IconButton(
onPressed: () {
_check();
},
icon: Icon(
_isCheck
? Icons.check_box_outlined
: Icons.check_box_outline_blank_outlined,
color: TColor.gray,
size: 20,
),
),
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"En continuant, vous acceptez notre Politique de\nconfidentialité et nos Conditions d'utilisation.",
style: TextStyle(color: TColor.gray, fontSize: 10),
),
)
],
),
SizedBox(
height: media.width * 0.05,
),
Visibility(
visible: _errorCreateUser,
child: Text("Error - $_msgError",
style: TextStyle(color: TColor.red))),
SizedBox(
height: media.width * 0.4,
),
RoundButton(
title: "Créer un compte",
onPressed: () async {
if (!emailValidate ||
!passwordValidate ||
!usernameValidate) {
_printMsgError(
"Les champs renseigné ne sont pas valide");
return;
}
Tuple2<bool, String> result = await util.createUser(
controllerTextEmail.text,
controllerUsername.text,
controllerTextPassword.text);
if (result.item1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginView()));
} else {
_printMsgError(result.item2);
}
}),
SizedBox(
height: media.width * 0.04,
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Ou ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
],
),
SizedBox(
height: media.width * 0.04,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginView()));
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous avez déjà un compte ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Se connecter",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w700),
)
],
),
),
SizedBox(
height: media.width * 0.04,
),
],
),
),
),
),
);
}
}

@ -1,14 +1,7 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter_svg/svg.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/View/login/login_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/round_text_field.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/view/login/mobile/android_signup_view.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
import 'package:smartfit_app_mobile/view/login/web/web_signup_view.dart';
class SignUpView extends StatefulWidget {
const SignUpView({super.key});
@ -18,252 +11,11 @@ class SignUpView extends StatefulWidget {
}
class _SignUpViewState extends State<SignUpView> {
bool _obscureText = true;
bool _errorCreateUser = false;
bool isCheck = false;
String _msgError = "";
IDataStrategy api = RequestApi();
final controllerTextEmail = TextEditingController();
final controllerTextUsername = TextEditingController();
final controllerTextPassword = TextEditingController();
Future<Tuple2<bool, String>> createUser() async {
return await api.postUser(
controllerTextEmail.text,
sha256.convert(utf8.encode(controllerTextPassword.text)).toString(),
controllerTextUsername.text);
}
// Toggles the password show status
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue,",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Créer un compte",
style: TextStyle(
color: TColor.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
),
const RoundTextField(
hitText: "Prénom",
icon: "assets/img/user_text.svg",
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Email",
icon: "assets/img/email.svg",
keyboardType: TextInputType.emailAddress,
controller: controllerTextEmail,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Mot de passe",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
controller: controllerTextPassword,
rigtIcon: TextButton(
onPressed: _toggle,
child: Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: SvgPicture.asset(
"assets/img/show_password.svg",
width: 20,
height: 20,
fit: BoxFit.contain,
))),
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
IconButton(
onPressed: () {
setState(() {
isCheck = !isCheck;
});
},
icon: Icon(
isCheck
? Icons.check_box_outlined
: Icons.check_box_outline_blank_outlined,
color: TColor.gray,
size: 20,
),
),
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"En continuant, vous acceptez notre Politique de\nconfidentialité et nos Conditions d'utilisation.",
style: TextStyle(color: TColor.gray, fontSize: 10),
),
)
],
),
Visibility(
visible: _errorCreateUser,
child: Text("Error - $_msgError",
style: TextStyle(color: TColor.red))),
SizedBox(
height: media.width * 0.4,
),
RoundButton(
title: "Créer un compte",
onPressed: () async {
Tuple2<bool, String> result = await createUser();
if (result.item1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginView()));
} else {
setState(() {
_errorCreateUser = true;
_msgError = result.item2;
});
}
}),
SizedBox(
height: media.width * 0.04,
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Ou ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
],
),
SizedBox(
height: media.width * 0.04,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginView()));
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous avez déjà un compte ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Se connecter",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w700),
)
],
),
),
SizedBox(
height: media.width * 0.04,
),
],
),
),
),
),
return ScreenTypeLayout.builder(
mobile: (_) => const MobileSignUpView(),
desktop: (_) => const WebSignUpView(),
);
}
}

@ -0,0 +1,297 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/modele/utile/login_user.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
import 'package:provider/provider.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/user.dart';
import 'package:smartfit_app_mobile/view/activity/list_activity.dart';
import 'package:smartfit_app_mobile/view/page_test.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/round_text_field.dart';
import 'package:tuple/tuple.dart';
class WebLoginView extends StatefulWidget {
const WebLoginView({super.key});
@override
State<WebLoginView> createState() => _WebLoginView();
}
class _WebLoginView extends State<WebLoginView> {
final Login util = Login();
bool _obscureText = true;
bool _errorLogin = false;
String _msgError = "";
bool emailValidate = false;
bool passwordValidate = false;
final controllerTextEmail = TextEditingController();
final controllerTextPassword = TextEditingController();
@override
void initState() {
super.initState();
// Start listening to changes.
controllerTextEmail.addListener(checkEmail);
controllerTextPassword.addListener(checkPassword);
}
// Toggles the password show status
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
void _printMsgError(String msgError) {
setState(() {
_msgError = msgError;
_errorLogin = true;
});
}
void checkEmail() {
/*
if (!controllerTextEmail.text.contains("@") &&
!(controllerTextEmail.text.length > 6)) {
emailValidate = false;
// Faire un affichage
return;
} // Enlever l'affichage*/
emailValidate = true;
}
void checkPassword() {
/*
if (!(controllerTextEmail.text.length >= 4)) {
passwordValidate = false;
//Faire un affichage
return;
} // Enlever l'affichage*/
passwordValidate = true;
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Container(
height: media.height * 0.9,
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Se connecter",
style: TextStyle(
color: TColor.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Email",
icon: "assets/img/email.svg",
keyboardType: TextInputType.emailAddress,
controller: controllerTextEmail,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
controller: controllerTextPassword,
hitText: "Mot de passe",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
rigtIcon: TextButton(
onPressed: _toggle,
child: Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: SvgPicture.asset(
"assets/img/show_password.svg",
width: 20,
height: 20,
fit: BoxFit.contain,
))),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Mot de passe oublié ?",
style: TextStyle(
color: TColor.gray,
fontSize: 15,
decoration: TextDecoration.underline),
),
],
),
SizedBox(
height: media.width * 0.04,
),
Visibility(
visible: _errorLogin,
child: Text("Error - $_msgError",
style: TextStyle(color: TColor.red))),
const Spacer(),
RoundButton(
title: "Se connecter",
onPressed: () async {
if (!emailValidate || !passwordValidate) {
_printMsgError(
"Les champs renseigné ne sont pas valide");
return;
}
Tuple2<bool, String> result =
await util.checkLoginAndPassword(
controllerTextEmail.text,
controllerTextPassword.text);
if (result.item1 == true) {
Tuple2 infoUser = await util.getUserInfo(result.item2);
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}");
} else {
util.fillUser(context, infoUser.item2, result.item2);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MainTabView()));
}
} else {
_printMsgError("Connexion refuser - ${result.item2}");
}
}),
SizedBox(
height: media.width * 0.04,
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Or ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
],
),
SizedBox(
height: media.width * 0.04,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous n'avez pas toujours pas de compte ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Créer un compte",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w700),
)
],
),
),
SizedBox(
height: media.width * 0.04,
),
],
),
),
),
),
);
}
}

@ -0,0 +1,321 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/modele/utile/signup_user.dart';
import 'package:smartfit_app_mobile/view/login/login_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/round_text_field.dart';
import 'package:tuple/tuple.dart';
class WebSignUpView extends StatefulWidget {
const WebSignUpView({super.key});
@override
State<WebSignUpView> createState() => _WebSignUpView();
}
class _WebSignUpView extends State<WebSignUpView> {
final SignUp util = SignUp();
bool _obscureText = true;
bool _errorCreateUser = false;
bool _isCheck = false;
String _msgError = "";
bool emailValidate = false;
bool passwordValidate = false;
bool usernameValidate = false;
final controllerTextEmail = TextEditingController();
final controllerUsername = TextEditingController();
final controllerTextPassword = TextEditingController();
@override
void initState() {
super.initState();
// Start listening to changes.
controllerTextEmail.addListener(checkEmail);
controllerTextPassword.addListener(checkPassword);
controllerUsername.addListener(checkUsername);
}
// Toggles the password show status
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
void _printMsgError(String msgError) {
setState(() {
_msgError = msgError;
_errorCreateUser = true;
});
}
void checkEmail() {
if (!controllerTextEmail.text.contains("@") &&
!(controllerTextEmail.text.length > 6)) {
emailValidate = false;
// Faire un affichage
return;
} // Enlever l'affichage
emailValidate = true;
}
void checkPassword() {
if (!(controllerTextEmail.text.length >= 4)) {
passwordValidate = false;
//Faire un affichage
return;
} // Enlever l'affichage
passwordValidate = true;
}
void checkUsername() {
if (controllerUsername.text.isEmpty) {
usernameValidate = false;
return;
}
usernameValidate = true;
}
void _check() {
setState(() {
_isCheck = !_isCheck;
});
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Bienvenue,",
style: TextStyle(color: TColor.gray, fontSize: 16),
),
Text(
"Créer un compte",
style: TextStyle(
color: TColor.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.05,
),
RoundTextField(
hitText: "Prénom",
icon: "assets/img/user_text.svg",
controller: controllerUsername,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Email",
icon: "assets/img/email.svg",
keyboardType: TextInputType.emailAddress,
controller: controllerTextEmail,
),
SizedBox(
height: media.width * 0.04,
),
RoundTextField(
hitText: "Mot de passe",
icon: "assets/img/lock.svg",
obscureText: _obscureText,
controller: controllerTextPassword,
rigtIcon: TextButton(
onPressed: _toggle,
child: Container(
alignment: Alignment.center,
width: 20,
height: 20,
child: SvgPicture.asset(
"assets/img/show_password.svg",
width: 20,
height: 20,
fit: BoxFit.contain,
))),
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
IconButton(
onPressed: () {
_check();
},
icon: Icon(
_isCheck
? Icons.check_box_outlined
: Icons.check_box_outline_blank_outlined,
color: TColor.gray,
size: 20,
),
),
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"En continuant, vous acceptez notre Politique de\nconfidentialité et nos Conditions d'utilisation.",
style: TextStyle(color: TColor.gray, fontSize: 10),
),
)
],
),
SizedBox(
height: media.width * 0.05,
),
Visibility(
visible: _errorCreateUser,
child: Text("Error - $_msgError",
style: TextStyle(color: TColor.red))),
SizedBox(
height: media.width * 0.4,
),
RoundButton(
title: "Créer un compte",
onPressed: () async {
if (!emailValidate ||
!passwordValidate ||
!usernameValidate) {
_printMsgError(
"Les champs renseigné ne sont pas valide");
return;
}
Tuple2<bool, String> result = await util.createUser(
controllerTextEmail.text,
controllerUsername.text,
controllerTextPassword.text);
if (result.item1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginView()));
} else {
_printMsgError(result.item2);
}
}),
SizedBox(
height: media.width * 0.04,
),
Row(
// crossAxisAlignment: CrossAxisAlignment.,
children: [
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
Text(
" Ou ",
style: TextStyle(color: TColor.black, fontSize: 12),
),
Expanded(
child: Container(
height: 1,
color: TColor.gray.withOpacity(0.5),
)),
],
),
SizedBox(
height: media.width * 0.04,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginView()));
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Vous avez déjà un compte ? ",
style: TextStyle(
color: TColor.black,
fontSize: 14,
),
),
Text(
"Se connecter",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w700),
)
],
),
),
SizedBox(
height: media.width * 0.04,
),
],
),
),
),
),
);
}
}

@ -1,11 +1,10 @@
import 'package:smartfit_app_mobile/View/activity/list_activity.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/tab_button.dart';
import 'package:smartfit_app_mobile/view/activity/activity.dart';
import 'package:smartfit_app_mobile/view/home/home_view.dart';
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/view/activity/list_activity.dart';
import 'package:smartfit_app_mobile/view/map/my_map.dart';
import 'package:smartfit_app_mobile/view/page_test.dart';
import 'package:smartfit_app_mobile/view/profile/profile_view.dart';
class MainTabView extends StatefulWidget {

@ -1,11 +1,7 @@
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
//import 'package:smartfit_app_mobile/view/meal_planner/meal_planner_view.dart';
//import 'package:smartfit_app_mobile/view/workout_tracker/workout_tracker_view.dart';
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/view/home/blank_view.dart';
//import '../sleep_tracker/sleep_tracker_view.dart';
//import '../sleep_tracker/sleep_tracker_view.dart';
/*
class SelectView extends StatelessWidget {
const SelectView({super.key});
@ -29,10 +25,10 @@ class SelectView extends StatelessWidget {
),
);
}),
const SizedBox(height: 15,),
RoundButton(
const SizedBox(
height: 15,
),
RoundButton(
title: "Meal Planner",
onPressed: () {
Navigator.push(
@ -42,10 +38,10 @@ class SelectView extends StatelessWidget {
),
);
}),
const SizedBox(height: 15,),
RoundButton(
const SizedBox(
height: 15,
),
RoundButton(
title: "Sleep Tracker",
onPressed: () {
Navigator.push(
@ -60,4 +56,5 @@ class SelectView extends StatelessWidget {
),
);
}
}
}
*/

@ -16,15 +16,12 @@ class _OnBoardingViewState extends State<OnBoardingView> {
@override
void initState() {
super.initState();
controller.addListener(() {
selectPage = controller.page?.round() ?? 0;
selectPage = controller.page?.round() ?? 0;
setState(() {
});
setState(() {});
});
}
@ -39,7 +36,7 @@ class _OnBoardingViewState extends State<OnBoardingView> {
"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.",
"image": "assets/img/on_2.svg"
"image": "assets/img/on_2.svg"
},
{
"title": "Laissez-nous piloter, mettez simplement votre Suunto",
@ -51,7 +48,6 @@ class _OnBoardingViewState extends State<OnBoardingView> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: TColor.white,
body: Stack(
@ -62,52 +58,52 @@ class _OnBoardingViewState extends State<OnBoardingView> {
itemCount: pageArr.length,
itemBuilder: (context, index) {
var pObj = pageArr[index] as Map? ?? {};
return OnBoardingPage(pObj: pObj) ;
return OnBoardingPage(pObj: pObj);
}),
SizedBox(
width: 120,
height: 120,
child: Stack(
alignment: Alignment.center,
children: [
SizedBox(
width: 70,
height: 70,
child: CircularProgressIndicator(
color: TColor.primaryColor1,
value: (selectPage + 1) / 3 ,
value: (selectPage + 1) / 3,
strokeWidth: 2,
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 30, vertical: 30),
margin:
const EdgeInsets.symmetric(horizontal: 30, vertical: 30),
width: 60,
height: 60,
decoration: BoxDecoration(color: TColor.primaryColor1, borderRadius: BorderRadius.circular(35)),
child: IconButton(icon: Icon( Icons.navigate_next, color: TColor.white, ), onPressed: (){
if(selectPage < 2) {
selectPage = selectPage + 1;
controller.animateToPage(selectPage, duration: const Duration(milliseconds: 200), curve: Curves.bounceInOut);
setState(() {
});
}else{
Navigator.push(context,
decoration: BoxDecoration(
color: TColor.primaryColor1,
borderRadius: BorderRadius.circular(35)),
child: IconButton(
icon: Icon(
Icons.navigate_next,
color: TColor.white,
),
onPressed: () {
if (selectPage < 2) {
selectPage = selectPage + 1;
controller.animateToPage(selectPage,
duration: const Duration(milliseconds: 200),
curve: Curves.bounceInOut);
setState(() {});
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SignUpView()
)
);
builder: (context) => const SignUpView()));
}
},),
},
),
),
],
),
)
@ -115,4 +111,4 @@ class _OnBoardingViewState extends State<OnBoardingView> {
),
);
}
}
}

@ -65,4 +65,4 @@ class _StartedViewState extends State<StartedView> {
)),
);
}
}
}

@ -1,17 +1,16 @@
/*import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:file_picker/file_picker.dart';
import 'dart:io';
import 'package:provider/provider.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/activity.dart';
import 'package:smartfit_app_mobile/Modele/manager_file.dart';
import 'package:smartfit_app_mobile/Modele/user.dart';
import 'dart:io';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:tuple/tuple.dart';
// ----------- File --------------- //
@ -48,6 +47,22 @@ Future<int> readCounter() async {
}
}
String getPlatforme() {
if (kIsWeb) {
return "Web";
}
if (Platform.isAndroid) {
return "Android";
}
if (Platform.isWindows) {
return "Windows";
}
if (Platform.isMacOS) {
return "MacOS";
}
return "Null";
}
// File picker
// ------------------------------------------------- //
@ -63,6 +78,7 @@ class _TestPage extends State<TestPage> {
// Lire un fichier avec picker
FilePickerResult? result;
IDataStrategy strategy = RequestApi();
String platforme = getPlatforme();
//late File x = File(file.path);
Future<void> readFile() async {
@ -105,7 +121,7 @@ class _TestPage extends State<TestPage> {
print(digest.toString());
print("Appel");
Tuple2<bool, String> res =
await strategy.connexion("toto@gmail.com", digest.toString());
await strategy.connexion("1234", digest.toString());
print(res.item1);
print(res.item2);
}
@ -121,7 +137,7 @@ class _TestPage extends State<TestPage> {
Future<void> getFiles() async {
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGUyYWVmMTItN2ZiNC0xMWVlLWJhZmQtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA0ODgyNzk3fQ.b_zsOHj2C-Y28CrcozbSjEz8BUWL8kgjjx5CDhES8PI";
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGJiNDdmMDAtODJkNi0xMWVlLTkzMTMtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA1MjI4MTUyfQ.9ADC65f2rNI_llytvhA6tX0NM9_O3-2RlwPXqV0yYcI";
print("Appel");
Tuple2 res = await strategy.getFiles(token);
print(res.item1);
@ -142,7 +158,7 @@ class _TestPage extends State<TestPage> {
Future<void> uploadFile() async {
PlatformFile t = result!.files.single;
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGUyYWVmMTItN2ZiNC0xMWVlLWJhZmQtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA0ODgzNjM5fQ.0TmfJ9eYnszw4_RkNwPkMzkJxvsIFs5BI9uhQ7qYb0g";
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGJiNDdmMDAtODJkNi0xMWVlLTkzMTMtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA1MjI4MTUyfQ.9ADC65f2rNI_llytvhA6tX0NM9_O3-2RlwPXqV0yYcI";
String? lol = t.path!;
print("Appel");
Tuple2 res = await strategy.uploadFile(token, File(lol));
@ -180,6 +196,8 @@ class _TestPage extends State<TestPage> {
@override
Widget build(BuildContext context) {
User w = context.watch<User>();
return Scaffold(
body: Column(
children: [
@ -220,7 +238,11 @@ class _TestPage extends State<TestPage> {
ElevatedButton(
onPressed: getOneFile, child: const Text("Get One File")),
ElevatedButton(
onPressed: getInfoUser, child: const Text("Get info User"))
onPressed: getInfoUser, child: const Text("Get info User")),
Text(platforme),
Text(w.email),
Text(context.watch<User>().username),
Text(Provider.of<User>(context).username)
],
),
);
@ -228,7 +250,6 @@ class _TestPage extends State<TestPage> {
}
/*
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
@ -292,7 +313,6 @@ class _MyHomePageState extends State<MyHomePage> {
title: Text(widget.title),
),
/*
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
@ -341,7 +361,6 @@ class _MyHomePageState extends State<MyHomePage> {
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
*/
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(8),
@ -386,5 +405,4 @@ class _MyHomePageState extends State<MyHomePage> {
),
);
}
}
*/*/
}*/

@ -0,0 +1,361 @@
import 'package:flutter/material.dart';
import 'package:animated_toggle_switch/animated_toggle_switch.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/setting_row.dart';
import 'package:smartfit_app_mobile/common_widget/title_subtitle_cell.dart';
class MobileProfileView extends StatefulWidget {
const MobileProfileView({super.key});
@override
State<MobileProfileView> createState() => _MobileProfileView();
}
class _MobileProfileView extends State<MobileProfileView> {
bool positive = false;
List accountArr = [
{
"image": "assets/img/p_personal.png",
"name": "Données personnelles",
"tag": "1"
},
];
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"
},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: TColor.white,
centerTitle: true,
elevation: 0,
leadingWidth: 0,
title: Text(
"Profile",
style: TextStyle(
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,
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset(
"assets/img/u1.png",
width: 50,
height: 50,
fit: BoxFit.cover,
),
),
const SizedBox(
width: 15,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Benjelloun Othmane",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
Text(
"Course à pied",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
)
],
),
),
SizedBox(
width: 70,
height: 25,
child: RoundButton(
title: "Editer",
type: RoundButtonType.bgGradient,
fontSize: 12,
fontWeight: FontWeight.w400,
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const ActivityTrackerView(),
// ),
// );
},
),
)
],
),
const SizedBox(
height: 15,
),
const Row(
children: [
Expanded(
child: TitleSubtitleCell(
title: "??? cm",
subtitle: "Taille",
),
),
SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? kg",
subtitle: "Poids",
),
),
SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? ans",
subtitle: "Age",
),
),
],
),
const SizedBox(
height: 25,
),
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(
"Compte",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: accountArr.length,
itemBuilder: (context, index) {
var iObj = accountArr[index] as Map? ?? {};
return SettingRow(
icon: iObj["image"].toString(),
title: iObj["name"].toString(),
onPressed: () {},
);
},
)
],
),
),
const SizedBox(
height: 25,
),
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(
"Notification",
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/p_notification.png",
height: 15, width: 15, fit: BoxFit.contain),
const SizedBox(
width: 15,
),
Expanded(
child: Text(
"Pop-up Notification",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
),
CustomAnimatedToggleSwitch<bool>(
current: positive,
values: [false, true],
spacing: 0.0,
indicatorSize: Size.square(25.0),
animationDuration:
const Duration(milliseconds: 200),
animationCurve: Curves.linear,
onChanged: (b) => setState(() => positive = b),
iconBuilder: (context, local, global) {
return const SizedBox();
},
cursors: ToggleCursors(
defaultCursor: SystemMouseCursors.click),
onTap: (_) =>
setState(() => positive = !positive),
iconsTappable: false,
wrapperBuilder: (context, global, child) {
return Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 10.0,
right: 10.0,
height: 20.0,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: TColor.secondaryG),
borderRadius:
const BorderRadius.all(
Radius.circular(50.0)),
),
)),
child,
],
);
},
foregroundIndicatorBuilder: (context, global) {
return SizedBox.fromSize(
size: const Size(5, 5),
child: DecoratedBox(
decoration: BoxDecoration(
color: TColor.white,
borderRadius: const BorderRadius.all(
Radius.circular(50.0)),
boxShadow: const [
BoxShadow(
color: Colors.black38,
spreadRadius: 0.05,
blurRadius: 1.1,
offset: Offset(0.0, 0.8))
],
),
),
);
},
),
]),
)
],
),
),
const SizedBox(
height: 25,
),
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(
"Autre",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: otherArr.length,
itemBuilder: (context, index) {
var iObj = otherArr[index] as Map? ?? {};
return SettingRow(
icon: iObj["image"].toString(),
title: iObj["name"].toString(),
onPressed: () {},
);
},
)
],
),
)
],
),
),
),
);
}
}

@ -1,10 +1,7 @@
import 'package:flutter/material.dart';
import '../../common/colo_extension.dart';
import '../../common_widget/round_button.dart';
import '../../common_widget/setting_row.dart';
import '../../common_widget/title_subtitle_cell.dart';
import 'package:animated_toggle_switch/animated_toggle_switch.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/view/profile/mobile/mobile_profile_view.dart';
import 'package:smartfit_app_mobile/view/profile/web/web_profile_view.dart';
class ProfileView extends StatefulWidget {
const ProfileView({super.key});
@ -14,341 +11,11 @@ class ProfileView extends StatefulWidget {
}
class _ProfileViewState extends State<ProfileView> {
bool positive = false;
List accountArr = [
{"image": "assets/img/p_personal.png", "name": "Données personnelles", "tag": "1"},
];
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"},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: TColor.white,
centerTitle: true,
elevation: 0,
leadingWidth: 0,
title: Text(
"Profile",
style: TextStyle(
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,
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset(
"assets/img/u1.png",
width: 50,
height: 50,
fit: BoxFit.cover,
),
),
const SizedBox(
width: 15,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Benjelloun Othmane",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
Text(
"Course à pied",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
)
],
),
),
SizedBox(
width: 70,
height: 25,
child: RoundButton(
title: "Editer",
type: RoundButtonType.bgGradient,
fontSize: 12,
fontWeight: FontWeight.w400,
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const ActivityTrackerView(),
// ),
// );
},
),
)
],
),
const SizedBox(
height: 15,
),
const Row(
children: [
Expanded(
child: TitleSubtitleCell(
title: "??? cm",
subtitle: "Taille",
),
),
SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? kg",
subtitle: "Poids",
),
),
SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? ans",
subtitle: "Age",
),
),
],
),
const SizedBox(
height: 25,
),
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(
"Compte",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: accountArr.length,
itemBuilder: (context, index) {
var iObj = accountArr[index] as Map? ?? {};
return SettingRow(
icon: iObj["image"].toString(),
title: iObj["name"].toString(),
onPressed: () {},
);
},
)
],
),
),
const SizedBox(
height: 25,
),
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(
"Notification",
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/p_notification.png",
height: 15, width: 15, fit: BoxFit.contain),
const SizedBox(
width: 15,
),
Expanded(
child: Text(
"Pop-up Notification",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
),
CustomAnimatedToggleSwitch<bool>(
current: positive,
values: [false, true],
spacing : 0.0,
indicatorSize: Size.square(25.0),
animationDuration:
const Duration(milliseconds: 200),
animationCurve: Curves.linear,
onChanged: (b) => setState(() => positive = b),
iconBuilder: (context, local, global) {
return const SizedBox();
},
cursors: ToggleCursors(defaultCursor: SystemMouseCursors.click),
onTap: (_) => setState(() => positive = !positive),
iconsTappable: false,
wrapperBuilder: (context, global, child) {
return Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 10.0,
right: 10.0,
height: 20.0,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: TColor.secondaryG),
borderRadius:
const BorderRadius.all(
Radius.circular(50.0)),
),
)),
child,
],
);
},
foregroundIndicatorBuilder: (context, global) {
return SizedBox.fromSize(
size: const Size(5, 5),
child: DecoratedBox(
decoration: BoxDecoration(
color: TColor.white,
borderRadius: const BorderRadius.all(
Radius.circular(50.0)),
boxShadow: const [
BoxShadow(
color: Colors.black38,
spreadRadius: 0.05,
blurRadius: 1.1,
offset: Offset(0.0, 0.8))
],
),
),
);
},
),
]),
)
],
),
),
const SizedBox(
height: 25,
),
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(
"Autre",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: otherArr.length,
itemBuilder: (context, index) {
var iObj = otherArr[index] as Map? ?? {};
return SettingRow(
icon: iObj["image"].toString(),
title: iObj["name"].toString(),
onPressed: () {},
);
},
)
],
),
)
],
),
),
),
return ScreenTypeLayout.builder(
mobile: (_) => const MobileProfileView(),
desktop: (_) => const WebProfileView(),
);
}
}
}

@ -0,0 +1,361 @@
import 'package:flutter/material.dart';
import 'package:animated_toggle_switch/animated_toggle_switch.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/setting_row.dart';
import 'package:smartfit_app_mobile/common_widget/title_subtitle_cell.dart';
class WebProfileView extends StatefulWidget {
const WebProfileView({super.key});
@override
State<WebProfileView> createState() => _WebProfileView();
}
class _WebProfileView extends State<WebProfileView> {
bool positive = false;
List accountArr = [
{
"image": "assets/img/p_personal.png",
"name": "Données personnelles",
"tag": "1"
},
];
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"
},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: TColor.white,
centerTitle: true,
elevation: 0,
leadingWidth: 0,
title: Text(
"Profile",
style: TextStyle(
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,
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset(
"assets/img/u1.png",
width: 50,
height: 50,
fit: BoxFit.cover,
),
),
const SizedBox(
width: 15,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Benjelloun Othmane",
style: TextStyle(
color: TColor.black,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
Text(
"Course à pied",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
)
],
),
),
SizedBox(
width: 70,
height: 25,
child: RoundButton(
title: "Editer",
type: RoundButtonType.bgGradient,
fontSize: 12,
fontWeight: FontWeight.w400,
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const ActivityTrackerView(),
// ),
// );
},
),
)
],
),
const SizedBox(
height: 15,
),
const Row(
children: [
Expanded(
child: TitleSubtitleCell(
title: "??? cm",
subtitle: "Taille",
),
),
SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? kg",
subtitle: "Poids",
),
),
SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? ans",
subtitle: "Age",
),
),
],
),
const SizedBox(
height: 25,
),
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(
"Compte",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: accountArr.length,
itemBuilder: (context, index) {
var iObj = accountArr[index] as Map? ?? {};
return SettingRow(
icon: iObj["image"].toString(),
title: iObj["name"].toString(),
onPressed: () {},
);
},
)
],
),
),
const SizedBox(
height: 25,
),
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(
"Notification",
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/p_notification.png",
height: 15, width: 15, fit: BoxFit.contain),
const SizedBox(
width: 15,
),
Expanded(
child: Text(
"Pop-up Notification",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
),
CustomAnimatedToggleSwitch<bool>(
current: positive,
values: [false, true],
spacing: 0.0,
indicatorSize: Size.square(25.0),
animationDuration:
const Duration(milliseconds: 200),
animationCurve: Curves.linear,
onChanged: (b) => setState(() => positive = b),
iconBuilder: (context, local, global) {
return const SizedBox();
},
cursors: ToggleCursors(
defaultCursor: SystemMouseCursors.click),
onTap: (_) =>
setState(() => positive = !positive),
iconsTappable: false,
wrapperBuilder: (context, global, child) {
return Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 10.0,
right: 10.0,
height: 20.0,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: TColor.secondaryG),
borderRadius:
const BorderRadius.all(
Radius.circular(50.0)),
),
)),
child,
],
);
},
foregroundIndicatorBuilder: (context, global) {
return SizedBox.fromSize(
size: const Size(5, 5),
child: DecoratedBox(
decoration: BoxDecoration(
color: TColor.white,
borderRadius: const BorderRadius.all(
Radius.circular(50.0)),
boxShadow: const [
BoxShadow(
color: Colors.black38,
spreadRadius: 0.05,
blurRadius: 1.1,
offset: Offset(0.0, 0.8))
],
),
),
);
},
),
]),
)
],
),
),
const SizedBox(
height: 25,
),
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(
"Autre",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: otherArr.length,
itemBuilder: (context, index) {
var iObj = otherArr[index] as Map? ?? {};
return SettingRow(
icon: iObj["image"].toString(),
title: iObj["name"].toString(),
onPressed: () {},
);
},
)
],
),
)
],
),
),
),
);
}
}

@ -0,0 +1,416 @@
/*import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:file_picker/file_picker.dart';
import 'package:provider/provider.dart';
import 'dart:io';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:tuple/tuple.dart';
// ----------- File --------------- //
// Dossier de l'application
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
// Uri du fichier
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/counter.txt');
}
Future<File> writeCounter(int counter) async {
final file = await _localFile;
// Write the file
return file.writeAsString('$counter');
}
Future<int> readCounter() async {
try {
final file = await _localFile;
// Read the file
final contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If encountering an error, return 0
return 0;
}
}
String getPlatforme() {
if (kIsWeb) {
return "Web";
}
if (Platform.isAndroid) {
return "Android";
}
if (Platform.isWindows) {
return "Windows";
}
if (Platform.isMacOS) {
return "MacOS";
}
return "Null";
}
// File picker
// ------------------------------------------------- //
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
@override
State<TestPage> createState() => _TestPage();
}
class _TestPage extends State<TestPage> {
// Lire un fichier avec picker
FilePickerResult? result;
IDataStrategy strategy = RequestApi();
String platforme = getPlatforme();
//late File x = File(file.path);
Future<void> readFile() async {
ManagerFile x = ManagerFile();
PlatformFile t = result!.files.single;
String? y = t.path;
if (t.path == null) {
print("t");
} else {
List<dynamic> result = await x.readFitFile(y!);
print("test11");
print(result);
print("test22");
print(ActivityOfUser(result).getHeartRateWithTime());
print("test33");
Provider.of<User>(context, listen: false).addActivity(ActivityOfUser(result));
//print(x.getDistanceWithTime(ActivityOfUser(result)));
//print(x.getDistance(ActivityOfUser(result)));
//print(x.getAltitudeWithTime(ActivityOfUser(result)));
//print(x.getSpeedWithTime(ActivityOfUser(result)));
}
}
Future<void> createUser() async {
String mds = "1234";
var byte = utf8.encode(mds);
var digest = sha256.convert(byte);
print(digest.toString());
print("Appel");
Tuple2<bool, String> res =
await strategy.postUser("toto@gmail.com", digest.toString(), "toto");
print(res.item1);
print(res.item2);
}
Future<void> login() async {
String mds = "1234";
var byte = utf8.encode(mds);
var digest = sha256.convert(byte);
print(digest.toString());
print("Appel");
Tuple2<bool, String> res =
await strategy.connexion("1234", digest.toString());
print(res.item1);
print(res.item2);
}
Future<void> deleteUser() async {
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiYjA3OThmMjAtN2ZiMy0xMWVlLWJhZmQtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA0ODgyNDI3fQ.2_bnvEC7_pwchielF3Kpu9fFtXDv_KabdOU8T07UnWI";
print("Appel");
Tuple2<bool, String> res = await strategy.deleteUser(token);
print(res.item1);
print(res.item2);
}
Future<void> getFiles() async {
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGJiNDdmMDAtODJkNi0xMWVlLTkzMTMtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA1MjI4MTUyfQ.9ADC65f2rNI_llytvhA6tX0NM9_O3-2RlwPXqV0yYcI";
print("Appel");
Tuple2 res = await strategy.getFiles(token);
print(res.item1);
print(res.item2);
}
Future<void> modifAttribut() async {
String nameAtt = "username";
String newValue = "toto2";
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGUyYWVmMTItN2ZiNC0xMWVlLWJhZmQtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA0ODgzMDM4fQ.umN7LmUDbKUOeIToLcsOUIioQ7u4wsReHggRDB68VPQ";
print("Appel");
Tuple2 res = await strategy.modifAttribut(token, nameAtt, newValue);
print(res.item1);
print(res.item2);
}
Future<void> uploadFile() async {
PlatformFile t = result!.files.single;
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGJiNDdmMDAtODJkNi0xMWVlLTkzMTMtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA1MjI4MTUyfQ.9ADC65f2rNI_llytvhA6tX0NM9_O3-2RlwPXqV0yYcI";
String? lol = t.path!;
print("Appel");
Tuple2 res = await strategy.uploadFile(token, File(lol));
print(res.item1);
print(res.item2);
}
Future<void> getOneFile() async {
String ui = "fc6e234c-7fc6-11ee-bafd-02420a5a001f";
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGUyYWVmMTItN2ZiNC0xMWVlLWJhZmQtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA0ODgzOTE3fQ.TUdrGEo7A0auQlUfO5RQm874QWuGXFBSKbJ8qTGPF2M";
print("Appel");
Tuple2 res = await strategy.getFile(token, ui);
print(res.item1);
print(res.item2);
ManagerFile x = ManagerFile();
File file = File("${await x.localPath}/Walking_2023-11-08T10_57_28.fit");
await file.create();
await file.writeAsBytes(res.item2);
print(await x.localPath);
print("Save");
print(await x
.readFitFile("${await x.localPath}/Walking_2023-11-08T10_57_28.fit"));
}
Future<void> getInfoUser() async {
String token =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiOGUyYWVmMTItN2ZiNC0xMWVlLWJhZmQtMDI0MjBhNWEwMDFmIiwiZXhwIjoxNzA0ODgzOTE3fQ.TUdrGEo7A0auQlUfO5RQm874QWuGXFBSKbJ8qTGPF2M";
Tuple2 res = await strategy.getInfoUser(token);
print(res.item1);
print(res.item2);
}
@override
Widget build(BuildContext context) {
User w = context.watch<User>();
return Scaffold(
body: Column(
children: [
const Text('A random AWESOME idea:'),
const Text("User"),
// Add this.
ElevatedButton(
onPressed: () {
print('button pressed!');
},
child: Text('Next'),
),
ElevatedButton(
onPressed: () async {
result = await FilePicker.platform.pickFiles();
if (result == null) {
print("No file selected");
} else {
for (var element in result!.files) {
print(element.name);
}
}
},
child: const Text("File - ")),
ElevatedButton(onPressed: login, child: const Text("Connexion")),
ElevatedButton(
onPressed: createUser, child: const Text("Create User")),
ElevatedButton(
onPressed: deleteUser, child: const Text("Delete User")),
ElevatedButton(
onPressed: readFile, child: const Text("ReadFile")),
ElevatedButton(onPressed: getFiles, child: const Text("getFiles")),
ElevatedButton(
onPressed: modifAttribut, child: const Text("modif attribut")),
ElevatedButton(
onPressed: uploadFile, child: const Text("Upload File")),
ElevatedButton(
onPressed: getOneFile, child: const Text("Get One File")),
ElevatedButton(
onPressed: getInfoUser, child: const Text("Get info User")),
Text(platforme),
Text(w.email),
Text(context.watch<User>().username),
Text(Provider.of<User>(context).username)
],
),
);
}
}
/*
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
void _updateText(String text) {
setState(() {
test = text;
});
}
IDataStrategy tmp = RequestApi();
//late Future<String> val = tmp.GetFile("x", "x");
late Future<String> val = tmp.test();
final TextEditingController _controller = TextEditingController();
String test = "Null";
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
/*
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
//
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
// action in the IDE, or press "p" in the console), to see the
// wireframe for each widget.
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('TEST'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
FutureBuilder<String>(
future: val,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Text(snapshot.data!)],
);
}
} else {
return const Text("FAIL");
}
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
*/
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(8),
child: FutureBuilder<String>(
future: val,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(snapshot.data!),
Text(test),
TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Enter Title',
),
),
ElevatedButton(
onPressed: () {
_updateText(_controller.text);
},
child: const Text('Update Data'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const TestPage()));
},
child: const Text("Changer de page"))
],
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
}
return const CircularProgressIndicator();
},
),
),
);
}
<<<<<<<< HEAD:lib/view/test/page_test.dart
}*/
========
}
*/*/
>>>>>>>> origin/master:lib/view/page_test.dart

@ -54,6 +54,7 @@ dependencies:
provider: ^6.0.5
tuple: ^2.0.2
crypto: ^3.0.3
responsive_builder: ^0.7.0
dev_dependencies:
flutter_test:

Loading…
Cancel
Save