diff --git a/covas_mobile/lib/main.dart b/covas_mobile/lib/main.dart index 4e58520..01f6a00 100644 --- a/covas_mobile/lib/main.dart +++ b/covas_mobile/lib/main.dart @@ -7,6 +7,7 @@ import 'dart:io'; //import 'MyHomePage.dart'; import 'pages/ListItemMenu.dart'; +import 'pages/AddProfile.dart'; import 'classes/alert.dart'; @@ -36,100 +37,73 @@ class _LoginDemoState extends State with ShowAlertDialog { TextEditingController inputPseudo = TextEditingController(); TextEditingController inputPassword = TextEditingController(); Future _login(BuildContext context) async { - var url = Uri.parse("${globals.api}/token"); - var pseudo = inputPseudo.text; - var password = inputPassword.text; - print("get login"); - print(pseudo.isNotEmpty); - print(password.isNotEmpty); - if ((pseudo.isNotEmpty) && (password.isNotEmpty)) { - print(url); - try { - //String credentials = "${pseudo}:${password}"; - //Codec stringToBase64 = utf8.fuse(base64); - //String encoded = stringToBase64.encode(credentials); - var response = await http.post(url, - // headers: { - // HttpHeaders.authorizationHeader: 'Basic $encoded', - //} - headers: { - 'accept': 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: { - "username": "${pseudo}", - "password": "${password}" - }); - print(response.statusCode); - if ((response.statusCode == 200) || (response.statusCode == 201)) { - SharedPreferences prefs = await SharedPreferences.getInstance(); + final url = Uri.parse("${globals.api}/token"); + final pseudo = inputPseudo.text; + final password = inputPassword.text; - var cookies = response.headers["set-cookie"].toString().split(";"); - for (var cookie in cookies) { - var cookiesMany = cookie.split(","); - for (var cookie2 in cookiesMany) { - switch (cookie2.split("=")[0]) { - case "access_token": - { - prefs.setString("access_token", cookie2.split("=")[1]); - } - break; - default: - break; - } + print("Attempting login"); + if (pseudo.isEmpty || password.isEmpty) { + showAlertDialog(context, "Erreur", "Champ vide"); + return; + } + + print("Request URL: $url"); + try { + final response = await http.post( + url, + headers: { + 'accept': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: { + "username": pseudo, + "password": password, + }, + ); + + print("Response status code: ${response.statusCode}"); + + if (response.statusCode == 200 || response.statusCode == 201) { + final prefs = await SharedPreferences.getInstance(); + final cookies = response.headers["set-cookie"]?.split(";") ?? []; + + for (final cookie in cookies) { + final cookieParts = cookie.split(","); + for (final part in cookieParts) { + final keyValue = part.split("="); + if (keyValue.length == 2 && keyValue[0] == "access_token") { + prefs.setString("access_token", keyValue[1]); } } - Navigator.push( - context, MaterialPageRoute(builder: (_) => ListItemMenu())); - } else { - var text = ""; - switch (response.statusCode) { - case 400: - { - text = "Requête mal construite"; - } - break; - case 406: - { - text = "Mot de passe incorrect"; - } - break; - case 404: - { - text = "Utilisateur inconnu"; - } - break; - case 403: - { - text = "Utilisateur desactive"; - } - break; - case 410: - { - text = "Token invalide"; - } - break; - case 500: - { - text = "Probleme interne du serveur"; - } - break; - default: - { - text = "Probleme d'authentification inconnu"; - } - break; - } - showAlertDialog(context, "Erreur serveur", text); } - } catch (e) { - showAlertDialog(context, "Erreur", "${e}"); + + Navigator.push( + context, + MaterialPageRoute(builder: (_) => ListItemMenu()), + ); + } else { + _handleErrorResponse(context, response.statusCode); } - } else { - showAlertDialog(context, "Erreur", "Champ vide"); + } catch (e) { + showAlertDialog(context, "Erreur", e.toString()); } } + void _handleErrorResponse(BuildContext context, int statusCode) { + final errorMessages = { + 400: "Requête mal construite", + 406: "Mot de passe incorrect", + 404: "Utilisateur inconnu", + 403: "Utilisateur désactivé", + 410: "Token invalide", + 500: "Problème interne du serveur", + }; + + final errorMessage = + errorMessages[statusCode] ?? "Problème d'authentification inconnu"; + showAlertDialog(context, "Erreur serveur", errorMessage); + } + void start() async { SharedPreferences prefs = await SharedPreferences.getInstance(); var access_token = prefs.getString("access_token") ?? ""; @@ -272,7 +246,12 @@ class _LoginDemoState extends State with ShowAlertDialog { SizedBox( height: 130, ), - Text('New User? Create Account') + InkWell( + child: Text('New User? Create Account'), + onTap: () { + Navigator.push( + context, MaterialPageRoute(builder: (_) => AddProfile())); + }) ], ), ), diff --git a/covas_mobile/lib/pages/AddProfile.dart b/covas_mobile/lib/pages/AddProfile.dart new file mode 100644 index 0000000..96d374b --- /dev/null +++ b/covas_mobile/lib/pages/AddProfile.dart @@ -0,0 +1,277 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; + +import 'dart:convert'; +import 'dart:io'; + +import '../main.dart'; + +import '../classes/alert.dart'; + +import '../variable/globals.dart' as globals; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + home: AddProfile(), + ); + } +} + +class AddProfile extends StatefulWidget { + const AddProfile({super.key}); + + @override + _AddProfileState createState() => _AddProfileState(); +} + +class _AddProfileState extends State with ShowAlertDialog { + TextEditingController inputUserName = TextEditingController(); + + TextEditingController inputName = TextEditingController(); + + TextEditingController inputFirstName = TextEditingController(); + TextEditingController inputEmail = TextEditingController(); + TextEditingController inputBirth = TextEditingController(); + TextEditingController inputPassword = TextEditingController(); + TextEditingController inputPasswordConfirmed = TextEditingController(); + + onTapFunctionDatePicker({required BuildContext context}) async { + DateTime? pickedDate = await showDatePicker( + context: context, + firstDate: DateTime(1900), + initialDate: DateTime.now(), + lastDate: DateTime(2104)); + if (pickedDate == null) return; + inputBirth.text = DateFormat("dd/MM/yyyy").format(pickedDate); + } + + convertNulltoEmptyString(var check) { + if (check == null) { + return ""; + } + return check; + } + + convertNulltoArray(List check) { + if (check == null) { + return []; + } + return check; + } + + String formatDate(String date) { + var splitedDate = date.split("/"); + + var day = splitedDate[0]; + var month = splitedDate[1]; + var year = splitedDate[2]; + + return "${year}-${month}-${day}"; + } + + Future _createProfile(BuildContext context) async { + var username = inputUserName.text; + var firstName = inputFirstName.text; + var name = inputName.text; + var email = inputEmail.text; + var password = inputPassword.text; + var confirmedPassword = inputPasswordConfirmed.text; + var birth = DateTime.parse(formatDate(inputBirth.text)); + + if ((password.isNotEmpty) && (confirmedPassword.isNotEmpty)) { + if (password != confirmedPassword) { + showAlertDialog(context, "Erreur", "Mot de passe different"); + return; + } + } + + var urlPut = Uri.parse("${globals.api}/mail"); + + var responsePost = await http.post(urlPut, + headers: { + HttpHeaders.acceptHeader: 'application/json, text/plain, */*', + HttpHeaders.contentTypeHeader: 'application/json' + }, + body: jsonEncode({ + 'name': name, + 'username': username, + 'firstName': firstName, + 'password': password, + 'email': email, + 'birth': birth.toString() + })); + print(responsePost.statusCode); + if (responsePost.statusCode == 200) { + showAlertDialog(context, "Creation", "Votre utilisateur a été créé"); + Navigator.pushReplacement( + context, MaterialPageRoute(builder: (_) => LoginDemo())); + return; + } + + final errorMessages = { + 400: "Requête mal construite", + 406: "Mot de passe incorrect", + 404: "Utilisateur inconnu", + 403: "Utilisateur désactivé", + 410: "Token invalide", + 500: "Problème interne du serveur", + }; + + final text = errorMessages[responsePost.statusCode] ?? + "Problème d'authentification inconnu"; + showAlertDialog(context, "Erreur serveur", text); + } + + @override + void initState() { + super.initState(); + } + + final _formKey = GlobalKey(); + String? _validateField(String? value) { + return value!.isEmpty ? 'Champ requis' : null; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + title: Text("Create profile"), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + body: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputUserName, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Pseudo', + hintText: 'Modifier le pseudo'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputPassword, + validator: (value) => _validateField(value), + obscureText: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Mot de passe', + hintText: 'Entrez le mot de passe'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputPasswordConfirmed, + validator: (value) => _validateField(value), + obscureText: true, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Confirmez le mot de passe', + hintText: 'Confirmez le mot de passe'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputName, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Nom', + hintText: 'Modifier le nom'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputFirstName, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Prénom', + hintText: 'Modifier le prénom'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputEmail, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Email', + hintText: 'Modifier l\'adresse mail'), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 15, bottom: 0), + //padding: EdgeInsets.symmetric(horizontal: 15), + child: TextFormField( + controller: inputBirth, + readOnly: true, + validator: (value) => _validateField(value), + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Date de naissance', + hintText: 'Cliquez ici pour selectionner une date'), + onTap: () => onTapFunctionDatePicker(context: context)), + ), + SizedBox( + height: 30, + ), + Container( + height: 50, + width: 250, + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(20)), + child: TextButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + _createProfile(context); + } + }, + child: Text( + 'Créer le profil', + style: TextStyle(color: Colors.white, fontSize: 25), + ), + ), + ) + ], + ), + ), + )); + } +}