# GoStyle [TOC] --- ## Membres du projet - Paul Barbaux - Ryan Jdaini - Le Hô - Enzo Compérat --- ## Technologies utilisées ### PHP ![](https://i.imgur.com/z4ROYIj.png =100x) > PHP est un langage serveur qui est fréquemment utilisé en web, il permet de faire la liaison entre notre code et notre BDD afin d'effectuer des requêtes quelconques. > Nous avons utilisé PHP pour les variables get qui communiquent avec mysql pour le back-end et qui renvoient une information en json, nous l'avons ensuite utilisée en service d'API ###### tags: `backend`,`server` ### MySql ![](https://i.imgur.com/gOnkRcY.png =100x) > Moteur de BDD très utilisé en web, > il stocke toutes les données relatives aux QR codes et aux utilisateurs > voici les modèles de nos tables de données : #### scan_user | id | email | password | admin | |:---:|:------------:|:------------:|:-------:| | int | varchar(255) | varchar(255) | booleen | #### scan_qr | id | value | promo | desc_promo | |:---:|:-----:|:------------:|:------------:| | int | Text | varchar(255) | varchar(255) | #### scan_email | id | email | qr_id | | --- |:------------:|:-----:| | int | varchar(255) | int | ###### tags: `backend`,`database technologies` ### flutter ![](https://i.imgur.com/hLOGdpc.png =100x) > Flutter est un Framework qui permet de faire des applications natives sur android, ios, web et desktop > il a été lancé par google en 2017 c'est le plus grand concurrent de React native créé par Facebook ###### tags: `dev mobile`,`new technologies`,`dart` ### Github ![](https://i.imgur.com/KLA8kRU.png =100x) >Github est un outil de gestion et de collaboration entre developpeurs >il est connu pour son aspect open-source. >Il utilise un outil appelé git pour pouvoir publier son code sur la plateforme. >Cette plateforme a été rachetée par microsoft en 2018. [le lien github du projet](https://github.com/polo5922/GoStyle) ###### tags: `open-source`,`code gestion`,`version gestion`,`GIT` --- ## Les avancements du projet - [x] Connexion/Inscription - [x] Liste des codes scannés - [x] Suppression des codes utilisés - [x] Ajout de code grâce à un QR code - [ ] Espace admin - [ ] Gestion des utilisateurs - [ ] Ajout de QR code --- ## Les fonctionalités ### Connexion/Inscription #### Package utilisé * [http](https://pub.dev/packages/http) #### Explication > Pour notre système de connexion et d'inscription nous avons un formulaire qui sert à nous connecter ou à nous inscrire. > Nos données sont envoyées à 2 pages ".dart" différentes en fonction du bouton sélectionné par l'utilisateur > L'envoi des données permet à la page d'effectuer une requête de connexion ou d'inscription qui vérifie si l'utilisateur existe ou si son adresse mail n'a pas déjà été utilisée, > si jamais l'adresse n'est pas enregistrée dans la BDD l'utilisateur est redirigé vers la page d'inscription et de connexion. #### Code ##### front-end > Exemple d'entrée de formulaire ``` dart TextFormField( decoration: const InputDecoration( hintText: 'Entrer votre email', ), validator: (value) { //le validator nous permet de rendre le champ valide si jamais il est vide ou si il ne contient pas de "@" le programme retourne false if (value.isEmpty) { return 'Ne pas entrer de valeur vide'; } if (value.contains('@') == false) { return 'Entrez un email valide'; } return null; }, controller: myControllerEmail, // le controller nous permet de recupérer le contenu de l'input ), ``` > Chaque TextFormField a son propre controller pour récupérer l'information écrite par l'utilisateur > Exemple de bouton ``` dart ElevatedButton( onPressed: () { // Validate will return true if the form is valid, or false if // the form is invalid. if (_formKey.currentState.validate()) { // si le formulaire est validé nous changeons de page avec les données d'email et de mdp Navigator.push( context, MaterialPageRoute( builder: (context) => Login( email: myControllerEmail.text, password: myControllerPassword.text, ), ), ); } }, child: Text('Connexion'), ), ``` > Ce bouton redirige vers la page de gestion de connexion avec en paramètre l'email et le mot de passe ##### back-end > login ``` php if ($type == "login") { if (isset($_GET['email'])) { $email = $_GET['email']; if (isset($_GET['password'])) { $password = $_GET['password']; $hpass = sha1(md5($password)); $sql = "SELECT * FROM scan_user WHERE email='$email' AND password='$hpass'"; $result = $conn->query($sql); if ($result->num_rows > 0) { echo "good:login"; } else { echo "bad:login"; } } } } ``` >register ``` php if ($type == "register") { if (isset($_GET['email'])) { $email = $_GET['email']; if (isset($_GET['password'])) { $password = $_GET['password']; $hpass = sha1(md5($password)); $sql2 = "SELECT * FROM scan_user WHERE email='$email'"; $result2 = $conn->query($sql2); if ($result2->num_rows == 0) { $sql = "INSERT INTO scan_user (email,password) VALUES ('$email','$hpass')"; if ($conn->query($sql)) { echo "good:register"; } else { echo "bad:register"; } } else { echo "bad:register:email_used"; } } } } ``` #### Screens > Page de connexion ![](https://i.imgur.com/l8NrB7W.jpg =300x) > Si la connexion est mauvaise ![](https://i.imgur.com/wbVFZpK.jpg =300x) > Si la connexion est bonne ![](https://i.imgur.com/PloaHUZ.jpg =300x) > Si le mail est déjà utilisé ![](https://i.imgur.com/GYVoC7N.jpg =300x) ### Liste des codes scannés #### Package utilisé * [http](https://pub.dev/packages/http) #### Explication >Afin de visualiser la liste des promotions scanées par l'utilisateur, une requête de récupération des "ID" liés à l'adresse mail de l'utilisateur a été éffectuée >Grâce à l'ID de la promotion qui vient d'être récupéré nous pouvons donc en déterminer les informations telles que la description et le code promo #### Code > Récupération de l'ensemble des ID ``` dart Future<Ids> fetchIds(email, type) async { var queryParameters = { 'type': type, 'email': email, }; String url = 'tartapain.bzh'; // nous paramétrons l'url de requête avec les variables get var uri = Uri.https(url, '/api/scan/get.php', queryParameters); final response = await http.get(uri); if (response.statusCode == 200) { // nous vérifions si la requête n'a pas eue de problème // si celle-ci n'a pas eue de problème, nous envoyons dans la fonction de décodage de json le résultat return Ids.fromJson(json.decode(response.body)); } else { throw Exception('Failed to load the post'); } } class Ids { final List<dynamic> ids; final int lenght; //nous créons 1'objet qui a 2 variables, les IDs et la length qui est relative au nombre d'éléments Ids({ this.ids, this.lenght, }); factory Ids.fromJson(Map<String, dynamic> json) { return Ids( // nous retournons les différents éléments grâce au contenu du json ids: json['ids'], lenght: json['lenght'], ); } } ``` > Reponse type JSON ``` json { "title": "20%SHOES", "desc": "20 % de réduction sur les chaussures" } ``` > Génération des différents éléments de la liste ``` dart FutureBuilder( initialData: [], future: futureIds, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: Text("Loading...")); // Affiche un texte "loading" en attente de la récuperation de tous les éléments } if (snapshot.hasData) { // nous vérifions si la réponse n'est pas vide if (snapshot.data.lenght == 0) { // si jamais nous n'avons pas d'élément alors un texte "pas de QR Code scanné" s'affiche return Padding( padding: const EdgeInsets.all(8.0), child: Center( child: Container( width: 200, height: 50, decoration: new BoxDecoration( color: Colors.blue, borderRadius: new BorderRadius.all( Radius.circular(20.0), ), ), child: Center( child: Text( "Pas de QR Code scanné", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14), ), ), ), ), ); } else { return SingleChildScrollView( child: Column( children: [ // si des données sont récupérées alors un widget custom CardDisplay est généré avec pour paramètres l'ID de la promotion scannée ainsi que le mail de l'utilisateur connecté for (var i = 0; i < snapshot.data.lenght; i++) CardDisplay( id: snapshot.data.ids[i], email: widget.email, ), ], ), ); } } else if (snapshot.hasError) { // si il y a des erreurs, nous les affichons via cette fonction return Text('${snapshot.error}'); } else { return CircularProgressIndicator( valueColor: new AlwaysStoppedAnimation<Color>(Colors.black)); } }, ), ``` #### Screens ![](https://i.imgur.com/0W8cEqO.jpg =300x) ### Suppression des codes utilisés #### Package utilisé * [http](https://pub.dev/packages/http) * [flutter_slidable](https://pub.dev/packages/flutter_slidable) #### Explication >Nous avons utilisé le package "flutter_slidable" pour nous permettre de rajouter des boutons d'action par effet de glissement (ce bouton ne peut apparaître que si l'utilisateur glisse un élément de la liste vers la droite). >Ce bouton est généré en même temps que les blocs de codes promos pour pouvoir être lié à l'ID d'un de ces blocs. #### Code > ajout du bouton de suppression ``` dart return Slidable( actionPane: SlidableScrollActionPane(), actions: <Widget>[ IconSlideAction( caption: 'Remove', color: Colors.red, icon: Icons.remove_circle_outline, onTap: () => { Navigator.push( context, MaterialPageRoute( builder: (context) => Remove( email: widget.email, //email de l utilisateur id: widget.id, // id du qr code ), ), ), }, ), ], actionExtentRatio: 1 / 5, ``` > le back relié à cette fonction ``` php if ($type == 'remove') { if (isset($_GET['id'])) { $id = $_GET['id']; // id du qr code if (isset($_GET['email'])) { $email = $_GET['email']; // email de l'utilisateur $sql = "DELETE FROM scan_email WHERE qr_id='$id' AND email='$email'"; if ($conn->query($sql)) { echo "code promo bien supprimé de votre profil"; } } } } ``` #### Screens > Bouton de suppression ![](https://i.imgur.com/mnYIozp.jpg =300x) > Confirmation de la suppression ![](https://i.imgur.com/JiWr2WN.jpg =300x) ### Ajout de code grâce à un QR code #### Package utilisée * [http](https://pub.dev/packages/http) * [flutter_barcode_scanner](https://pub.dev/packages/flutter_barcode_scanner) #### Explication > Nous avons utilisé le package "flutter_barcode_scanner" pour pouvoir simplifier le scan de QR code en quelques fonctions. > Nous récupérons ensuite la valeur du QR code scanné afin de vérifier si l'utilisateur a déjà lié ce code à son compte, si ce n'est pas le cas, nous pouvons l'enregistrer dans la BDD > > Si cet utilisateur a déjà scanné ce QR code alors il aura un message d'erreur lui indiquant qu'il l'a déjà scanné. #### Code >Ajout de la fonction de scan de QR CODE ``` dart Future<void> scanQR() async { String barcodeScanRes; try { barcodeScanRes = await FlutterBarcodeScanner.scanBarcode( "#ff6666", "Cancel", true, ScanMode.QR); // nous paramétrons le qr code avec le package "flutter_barcode_scanner" print(barcodeScanRes); } on PlatformException { barcodeScanRes = 'Failed to get platform version.'; // affichage de l'erreur si il y en a une } if (!mounted) return; setState(() { _scanBarcode = barcodeScanRes; // récupération de la valeur du qr code Navigator.push( context, MaterialPageRoute( // envois vers la page de traitement du qr code builder: (context) => QrResult( email: widget.email, // email de l'utilisateur qrValue: _scanBarcode, // valeur du qr code ))); }); } ``` > Page de traitement du qr code ``` php if ($type == 'add_user_qr') { if (isset($_GET['qr_value'])) { $qr_value = $_GET['qr_value']; // valeur du qr code if (isset($_GET['email'])) { $email = $_GET['email']; // valeur email de l'utilisateur $sql = "SELECT * FROM scan_qr WHERE value='$qr_value'"; // récupération de l'id du qr code dans la BDD $result = $conn->query($sql); if ($result->num_rows > 0) { while ($row = $result->fetch_assoc()) { $id = $row['id']; $sql2 = "SELECT * FROM scan_email WHERE qr_id='$id' AND email='$email'"; // recherche si l'utilisateur a déjà scanné le qr code $result2 = $conn->query($sql2); if ($result2->num_rows == 0) { $sql3 = "INSERT INTO scan_email (email,qr_id) VALUES ('$email','$id')"; if ($conn->query($sql3)) { echo '{"title":"Promotion bien sauvegardée","color":"green"}'; // si cet utilisateur n'avais pas déjà scanné le qr code alors celui-ci est ajouté à la liste } } else { // sinon il est indiqué comme étant déjà utilisé echo '{"title":"vous avez déjà scanné ce qr code","color":"red"}'; } } } else { // si le qr code n'est pas dans la BDD je renvoie donc à l'utilisateur que le QR code n'est pas valide echo '{"title":"ce n\'est pas un qr code valide","color":"red"}'; } } } } ``` #### Screens > Ajout du QR code ![](https://i.imgur.com/S2E3cZ8.jpg =300x) > QR code déjà scanné ![](https://i.imgur.com/XiOWSwc.jpg =300x) --- ### Espace admin > En cours de développement #### Explication > Un espace de gestion des différents utilisateurs ainsi que des différentes promotions en cours. > Panels : - Utilisateur - Code promo ### Ajout de QR code > En cours de développement #### Explication > Un élément qui permettra de mettre en ligne des nouvelles promotions > en rentrant - Le Code Promo - La Description > ce qui va permettre de le sauvegarder en ligne et d'envoyer à l'utilisateur l'image du QR code dans sa galerie pour pouvoir ensuite l'utiliser dans ses publicités.