diff --git a/Appels d'offre/DCE _CDCF_CDCT G1B-6.zip b/Appels d'offre/DCE _CDCF_CDCT G1B-6.zip new file mode 100644 index 00000000..6ec4d7b6 Binary files /dev/null and b/Appels d'offre/DCE _CDCF_CDCT G1B-6.zip differ diff --git a/Appels d'offre/SAE-DevApp CDCF-CDCT-DCE G1A-1.rar b/Appels d'offre/SAE-DevApp CDCF-CDCT-DCE G1A-1.rar new file mode 100644 index 00000000..1471d986 Binary files /dev/null and b/Appels d'offre/SAE-DevApp CDCF-CDCT-DCE G1A-1.rar differ diff --git "a/Base de donn\303\251es/G1B-6 Semaine 1.pdf" "b/Base de donn\303\251es/G1B-6 Semaine 1.pdf" new file mode 100644 index 00000000..d728678f Binary files /dev/null and "b/Base de donn\303\251es/G1B-6 Semaine 1.pdf" differ diff --git "a/Base de donn\303\251es/G1B-6 Semaine 2.pdf" "b/Base de donn\303\251es/G1B-6 Semaine 2.pdf" new file mode 100644 index 00000000..37337fbc Binary files /dev/null and "b/Base de donn\303\251es/G1B-6 Semaine 2.pdf" differ diff --git "a/Base de donn\303\251es/G1B-6 Semaine 49.pdf" "b/Base de donn\303\251es/G1B-6 Semaine 49.pdf" new file mode 100644 index 00000000..03e0ee2b Binary files /dev/null and "b/Base de donn\303\251es/G1B-6 Semaine 49.pdf" differ diff --git "a/Base de donn\303\251es/G1B-6 Semaine 50 .pdf" "b/Base de donn\303\251es/G1B-6 Semaine 50 .pdf" new file mode 100644 index 00000000..8dfdf842 Binary files /dev/null and "b/Base de donn\303\251es/G1B-6 Semaine 50 .pdf" differ diff --git "a/Communication/G1B-6 CR ODJ_CR R\303\251union_Analyse.pdf" "b/Communication/G1B-6 CR ODJ_CR R\303\251union_Analyse.pdf" new file mode 100644 index 00000000..3d6ce2cd Binary files /dev/null and "b/Communication/G1B-6 CR ODJ_CR R\303\251union_Analyse.pdf" differ diff --git a/Communication/G1B-6 CR Speed Datings.pdf b/Communication/G1B-6 CR Speed Datings.pdf new file mode 100644 index 00000000..8f3b8f1a Binary files /dev/null and b/Communication/G1B-6 CR Speed Datings.pdf differ diff --git "a/Communication/G1B-6 semaine 1 ODJ_CR R\303\251union_Analyse.pdf" "b/Communication/G1B-6 semaine 1 ODJ_CR R\303\251union_Analyse.pdf" new file mode 100644 index 00000000..fca2d254 Binary files /dev/null and "b/Communication/G1B-6 semaine 1 ODJ_CR R\303\251union_Analyse.pdf" differ diff --git "a/Communication/G1B-6 semaine 2 ODJ_CR R\303\251union_Analyse.pdf" "b/Communication/G1B-6 semaine 2 ODJ_CR R\303\251union_Analyse.pdf" new file mode 100644 index 00000000..94b2c5e1 Binary files /dev/null and "b/Communication/G1B-6 semaine 2 ODJ_CR R\303\251union_Analyse.pdf" differ diff --git "a/Communication/G1B-6 semaine 3 ODJ_CR R\303\251union post-mortem.pdf" "b/Communication/G1B-6 semaine 3 ODJ_CR R\303\251union post-mortem.pdf" new file mode 100644 index 00000000..8dc58177 Binary files /dev/null and "b/Communication/G1B-6 semaine 3 ODJ_CR R\303\251union post-mortem.pdf" differ diff --git "a/Communication/G1B-6 semaine 50 ODJ_CR R\303\251union_Analyse.pdf" "b/Communication/G1B-6 semaine 50 ODJ_CR R\303\251union_Analyse.pdf" new file mode 100644 index 00000000..a16dcf15 Binary files /dev/null and "b/Communication/G1B-6 semaine 50 ODJ_CR R\303\251union_Analyse.pdf" differ diff --git a/Documentation Java/G1B-6 Documentation technique Java.pdf b/Documentation Java/G1B-6 Documentation technique Java.pdf new file mode 100644 index 00000000..afc9689f Binary files /dev/null and b/Documentation Java/G1B-6 Documentation technique Java.pdf differ diff --git a/Documentation Python/G1B-6 Python.zip b/Documentation Python/G1B-6 Python.zip new file mode 100644 index 00000000..341a06a3 Binary files /dev/null and b/Documentation Python/G1B-6 Python.zip differ diff --git a/Documentation/Backlog Produit IOT & E-commerce.adoc b/Documentation/Backlog Produit IOT & E-commerce.adoc new file mode 100644 index 00000000..462c5ebe --- /dev/null +++ b/Documentation/Backlog Produit IOT & E-commerce.adoc @@ -0,0 +1,34 @@ += Backlog produit de l'application IOT et du site d'e-commerce, réalisé par Esteban BIRET-TOSCANO. +:toc: +:toc-title: Sommaire +:numbered: + +== Application IOT + +|======= +|Numéro |User Story |Priorité|Critères d'acceptation +|1 |En tant qu'utilisateur, je souhaite pouvoir configurer les paramètres, afin de visualiser les données de mon choix. |Haute|IHM intuitive / Ecriture du .yml par JAVA, et lecture du .yml par Python / Configuration des information à afficher, du seuil maximum, des devices et du temps de rafraichissement. +|2|En tant qu'utilisateur, je veux pouvoir lire les informations choisies précédemment. |Haute| Affichage des données en question sur l'IHM. +|3 |En tant qu'utilisateur, j'aimerais pouvoir visualiser ces informations sous forme de graphiques, afin d'améliorer la visibilité.|Moyenne| Affichage des graphiques sur l'IHM. +|======= + +== Site E-commerce + +|======= +|Numéro |User Story |Priorité|Critères d'acceptation +|1 |En tant que visiteur, je souhaite faire une recherche d'un sous-marin par nom, afin d'obtenir la liste des produits avec leurs prix.|Haute|Sur la page d'accueil, un bouton 'Nos produits' permet d'afficher la page des produits, avec une barre de recherche. +|2|En tant que visiteur, je souhaite faire une recherche d'un sous-marin à l'aide ces catégories, afin d'obtenir la liste des produits avec leurs prix. |Haute|Sur la page d'accueil, un bouton 'Nos produits' permet d'afficher la page des produits, avec un menu présentant les 6 catégories. +|3 |En tant que visiteur, je veux pouvoir créer un compte SubOne afin de faire des achats.|Haute| Sur la page d'accueil, un bouton 'Connexion' permet d'afficher un formulaire de connexion. Un lien est présent dans ce formulaire, qui sert à créer un compte. +|4 |En tant que visiteur, je veux pouvoir afficher le détail d'un produit, afin de bénéficier d'informations supplémentaires.|Haute| Sur chaque produit, un bouton 'Informations' permet d'afficher une page qui présente le produit. +|5 |En tant que visiteur, je souhaite consulter les coordonnées de l'entreprise, afin d'en savoir plus et de les contacter au besoin.|Moyenne| Sur la page d'accueil, un bouton 'Contact' permet d'afficher les informations de SubOne. +|6 |En tant que client, je veux pouvoir me connecter à mon compte SubOne afin de faire des achats et de voir les informations de mon compte|Haute| Sur la page d'accueil, un bouton 'Connexion' permet d'afficher un formulaire de connexion. +|7 |En tant que client, je veux pouvoir modifier les informations de mon compte|Haute| Sur la page d'accueil, un bouton 'Compte client' ramène sur une page présentant les informations du client, et un bouton 'Modifier' ramène vers un formulaire de modification, où le client peut modifier toutes ses informations personnelles. +|8 |En tant que client, je veux pouvoir supprimer mon compte.|Haute| Sur la page d'accueil, un bouton 'Compte client' ramène sur une page présentant les informations du client, et un bouton 'Supprimer' permet de supprimer le compte, après une validation de la part du client. +|9 |En tant que client, je veux pouvoir ajouter un article à mon panier et choisir sa quantité.|Haute| Après avoir consulté le détail d'un produit, je peux l'ajouter au panier en choisissant sa quantité, à l'aide d'un input de type number et d'un bouton 'Ajouter au panier'. +|10 |En tant que client, je veux pouvoir retirer un ou plusieurs articles de mon panier.|Haute| Sur le panier, un bouton 'Supprimer' ainsi qu'un champ input number sont présent sur la carte de chaque article, permettant de retirer le nombre choisi d'articles du panier actuel. +|11 |En tant que client, je veux pouvoir consulter les informations de mon panier (prix et quantité).|Haute| Sur la page du panier, le prix total de celui-ci est affiché dynamiquement. Sur chaque article du panier, la quantité commandée est affichée. +|12 |En tant que client, je veux pouvoir supprimer l'intégralité de mon panier.|Haute| Sur le panier, un bouton 'Supprimer' permet de supprimer le panier. Le client reste sur son panier, mais ce dernier affiche désormais 'Votre panier est vide !', et un bouton invite le client à consulter les produits du site. +|13 |En tant que client, je veux pouvoir valider mon panier.|Haute| Sur le panier, un bouton 'Valider' permet d'afficher la page de commande. +|14 |En tant que client, je veux pouvoir valider ma commande.|Haute| Une fois sur la page de commande et après avoir rempli mes information de paiement (correctement), je clique sur le bouton 'Valider ma commande'. +|15 |En tant qu’administrateur du site, je souhaite pouvoir modifier le stock de mes articles.|Moyenne|Sur la page d'accueil, je tape 'admin'. J'accède à l'espace administrateur, où je peux modifier à ma guise le stock des articles. +|======= diff --git a/Documentation/Backlog Produit Sprint 6.adoc b/Documentation/Backlog Produit Sprint 6.adoc new file mode 100644 index 00000000..fde11b8b --- /dev/null +++ b/Documentation/Backlog Produit Sprint 6.adoc @@ -0,0 +1,26 @@ += Backlog Sprint 6, réalisé par Esteban BIRET-TOSCANO & Enzo Mancini. +:toc: +:toc-title: Sommaire +:numbered: + +== Application IOT (Enzo) + +|======= +|User Story |Tâches associées|Estimation (en heures) +|1 - En tant qu'utilisateur, je souhaite pouvoir configurer les paramètres, afin de visualiser les données de mon choix. |Ajout d'un bouton CONFIGURATION qui ouvre une nouvelle fenêtre dans lequel les Max, Min, seuil de danger, le pas et le capteur actuels (dans le fichier config.yml) sont affichés et modifiables.|5 +|2 - En tant qu'utilisateur, je veux pouvoir lire les informations choisies précédemment. |Ajout d'un bouton VALIDER sur la page de configuration qui va changer le fichier config.yml avec les données saisies et un thread actualise la page.| 7 +|3 - En tant qu'utilisateur, j'aimerais pouvoir visualiser ces informations sous forme de graphiques, afin d'améliorer la visibilité.|Utilisation de trois graphique (BarChar) sur lequel le niveau actuel (CO2,Température ou Humidité)est montré grâce à une première barre et une deuxième représente le seuil de danger, les graphiques sont actualisés toute les dix minustes grâce à un thread.| 15 +|======= + +== Site E-commerce (Esteban) + +|======= +|User Story |Tâches associées|Estimation (en heures) +|8 - En tant que client, je veux pouvoir supprimer mon compte.|Ajout du bouton 'Supprimer' sur la page du compte client, qui quand cliqué affiche un pop-up de confimation.Si oui, alors redirigé à une page de traitement (invisible pour le client)| 0.2 +|8 - En tant que client, je veux pouvoir supprimer mon compte.|La page de traitement supprime le client, le contenu du panier et le panier du client dans la base de données | 0.5 +|9 - En tant que client, je veux pouvoir ajouter un article à mon panier et choisir sa quantité.|Création d'un formulaire contenant un Input de type number et un bouton submit'ajouter au panier'| 1 +|9 - En tant que client, je veux pouvoir ajouter un article à mon panier et choisir sa quantité.|Une fois formulaire soumis, une page de traitement s'occupe d'insérer les données dans le panier du client, et ce dernier et redirigé vers son panier, et peut voir le contenu et le prix| 3 +|10 - En tant que client, je veux pouvoir retirer un article de mon panier.|Suppression de l'article en question via un bouton 'Supprimer', présent sur chaque article du panier| 0.2 +|11 - En tant que client, je veux pouvoir consulter les informations de mon panier (prix et quantité).|Calcul du prix du panier en fonction des articles et de leurs quantités, et quantité affichée sur chaque article| 5 +|12 - En tant que client, je veux pouvoir supprimer l'intégralité de mon panier.|Bouton 'Supprimer' tout en haut de la page du panier, qui supprime le contenu du panier du client | 0.3 +|======= diff --git a/Documentation/Backlog Produit Sprint 7.adoc b/Documentation/Backlog Produit Sprint 7.adoc new file mode 100644 index 00000000..12f4521f --- /dev/null +++ b/Documentation/Backlog Produit Sprint 7.adoc @@ -0,0 +1,26 @@ += Backlog Sprint 7, réalisé par Esteban BIRET-TOSCANO & Enzo Mancini. +:toc: +:toc-title: Sommaire +:numbered: + +== Application IOT (Enzo) + +|======= +|User Story |Tâches associées|Estimation (en heures) +|2 - En tant qu'utilisateur, je veux pouvoir lire les informations choisies précédemment. |Ajout d'un bouton VALIDER sur la page de configuration qui va changer le fichier config.yml avec les données saisies et un thread actualise la page.| 7 +|3 - En tant qu'utilisateur, j'aimerais pouvoir visualiser ces informations sous forme de graphiques, afin d'améliorer la visibilité.|Utilisation de trois graphique (BarChar) sur lequel le niveau actuel (CO2,Température ou Humidité)est montré grâce à une première barre et une deuxième représente le seuil de danger, les graphiques sont actualisés toute les dix minustes grâce à un thread.| 15 +|======= + +== Site E-commerce (Esteban) + +|======= +|User Story |Tâches associées|Estimation (en heures) +|13 - En tant que client, je veux pouvoir valider mon panier.|Ajout du bouton 'Valider' sur la page du panier, qui quand cliqué ramène vers la page 'commande.php', qui comporte un formulaire pour remplir les informations de paiement.| 0.2 +|14 - En tant que client, je veux pouvoir valider ma commande.|Création du formulaire de paiement et de son style css. Création des REGEX associées pour chaque champ et création de pop-up en fonction des champs non-conformes | 3 +|11 - En tant que client, je veux pouvoir consulter les informations de mon panier (prix et quantité).| Ajout d'un bouton 'Retour au panier' sur la page 'commande.php'.|0.2 +|14 - En tant que client, je veux pouvoir valider ma commande.|Après avoir validé la commande, suppression côté BD du contenu du panier ET du panier du client, et ajout de la commande dans la table 'Commande'. Ajout des articles commandés dans la table 'detailCommande', pour que l'utilisateur puisse consulter toutes ses commandes. Redirection vers la page d'accueil à l'aide d'un pop-up confirmant le passage de la commande.| 1.5 +|15 - En tant qu'administrateur du site, je souhaite pouvoir modifier le stock de mes articles.|Création du script JS permettant d'accéder à cet espace depuis l'accueil| 0.5 +|15 - En tant qu'administrateur du site, je souhaite pouvoir modifier le stock de mes articles.|Création de la page de Gestion et de son style| 0.8 +|15 - En tant qu'administrateur du site, je souhaite pouvoir modifier le stock de mes articles.|Création de la page d'ajout de stock et de son style| 1 +|15 - En tant qu'administrateur du site, je souhaite pouvoir modifier le stock de mes articles.|Création de la page de retrait de stock et de son style| 1 +|======= diff --git a/Documentation/Documentation technique WEB V6.pdf b/Documentation/Documentation technique WEB V6.pdf new file mode 100644 index 00000000..7465e4de Binary files /dev/null and b/Documentation/Documentation technique WEB V6.pdf differ diff --git a/Documentation/Documentation utilisateur WEB V6.pdf b/Documentation/Documentation utilisateur WEB V6.pdf new file mode 100644 index 00000000..7c259fa9 Binary files /dev/null and b/Documentation/Documentation utilisateur WEB V6.pdf differ diff --git "a/Documentation/Documentation utilisateur WEB finalis\303\251e (V6.1).pdf" "b/Documentation/Documentation utilisateur WEB finalis\303\251e (V6.1).pdf" new file mode 100644 index 00000000..19c04007 Binary files /dev/null and "b/Documentation/Documentation utilisateur WEB finalis\303\251e (V6.1).pdf" differ diff --git a/Documentation/Droit analyse impact.pdf b/Documentation/Droit analyse impact.pdf new file mode 100644 index 00000000..e2efadd7 Binary files /dev/null and b/Documentation/Droit analyse impact.pdf differ diff --git "a/D\303\251veloppement Web/G1B-6 CharteGraphique.pdf" "b/D\303\251veloppement Web/G1B-6 CharteGraphique.pdf" new file mode 100644 index 00000000..0f2fafa0 Binary files /dev/null and "b/D\303\251veloppement Web/G1B-6 CharteGraphique.pdf" differ diff --git "a/D\303\251veloppement Web/G1B-6 SEP.pdf" "b/D\303\251veloppement Web/G1B-6 SEP.pdf" new file mode 100644 index 00000000..48af2baa Binary files /dev/null and "b/D\303\251veloppement Web/G1B-6 SEP.pdf" differ diff --git "a/D\303\251veloppement Web/G1B-6 Semaine 1.pdf" "b/D\303\251veloppement Web/G1B-6 Semaine 1.pdf" new file mode 100644 index 00000000..5e9443c6 Binary files /dev/null and "b/D\303\251veloppement Web/G1B-6 Semaine 1.pdf" differ diff --git "a/D\303\251veloppement Web/G1B-6 Semaine 2.pdf" "b/D\303\251veloppement Web/G1B-6 Semaine 2.pdf" new file mode 100644 index 00000000..ebfdca66 Binary files /dev/null and "b/D\303\251veloppement Web/G1B-6 Semaine 2.pdf" differ diff --git "a/D\303\251veloppement Web/G1B-6 Session-Cookie.pdf" "b/D\303\251veloppement Web/G1B-6 Session-Cookie.pdf" new file mode 100644 index 00000000..ea346f72 Binary files /dev/null and "b/D\303\251veloppement Web/G1B-6 Session-Cookie.pdf" differ diff --git a/Fichiers src IOT/Avantages YML.odt b/Fichiers src IOT/Avantages YML.odt new file mode 100644 index 00000000..cd2ad8b1 Binary files /dev/null and b/Fichiers src IOT/Avantages YML.odt differ diff --git a/Fichiers src IOT/G1B-6.jar b/Fichiers src IOT/G1B-6.jar new file mode 100644 index 00000000..96e84ca4 Binary files /dev/null and b/Fichiers src IOT/G1B-6.jar differ diff --git a/Fichiers src IOT/Java src/AppConfig.java b/Fichiers src IOT/Java src/AppConfig.java new file mode 100644 index 00000000..894f53a6 --- /dev/null +++ b/Fichiers src IOT/Java src/AppConfig.java @@ -0,0 +1,68 @@ +package app.appsae; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import java.io.IOException; + +/** + * Classe de la fenêtre de configurations + * */ +public class AppConfig{ + private Stage secondStage; + private BorderPane secondPane; + + + /** + * Méthode start() pour commencer la fenêtre + * */ + public void start(){ + //on instancie le borderpane, la scene et le stage + this.secondPane = new BorderPane(); + Scene secondScene = new Scene(secondPane); + this.secondStage = new Stage(); + + //on choisit un titre, on met la scene dans le stage + secondStage.setTitle("AppSAE Configuration"); + secondStage.setScene(secondScene); + //on empêche de changer la taille de la fenêtre manuellement + secondStage.setResizable(false); + + //on lance la méthode config + Config(); + + //on montre la page + secondStage.show(); + } + + /** + * Méthode qui charge le fxml et le lie à la page + * */ + public void Config(){ + try { + //on créait un objet FXMLLoader + FXMLLoader loader = new FXMLLoader(); + //on lui donne le chemin de notre fichier fxml de la page + loader.setLocation(AppSAE.class.getResource("AppConfig.fxml")); + + //on charge le borderpane avec le fxml + BorderPane app = loader.load(); + + //on récupère le controller pour utiliser ses méthodes + AppConfigController ctrl = loader.getController(); + + //on utilise la méthode setFenetrePrincipale du controller pour lui dire que c'est cette page qu'il devra fermer + ctrl.setFenetrePrincipale(secondStage); + + secondPane.setCenter(app); + + }catch (IOException e) { + System.out.println("Config(): "+e.getMessage()); + System.exit(1); + } + } + + + +} diff --git a/Fichiers src IOT/Java src/AppConfigController.java b/Fichiers src IOT/Java src/AppConfigController.java new file mode 100644 index 00000000..7a42e13b --- /dev/null +++ b/Fichiers src IOT/Java src/AppConfigController.java @@ -0,0 +1,226 @@ +package app.appsae; + +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.*; +import javafx.stage.Stage; +import org.yaml.snakeyaml.Yaml; + +import java.io.File; +import java.io.PrintWriter; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.ResourceBundle; + +/** + * Controller de la page de configuration + * */ +public class AppConfigController implements Initializable { + + private Stage fenetrePrincipale; + + //private final AppSAEController appsaecontr = new AppSAEController(); + final private Reader reader= new Reader(); + + private Map data; + @FXML + private Spinner maxCO2; + @FXML + private Spinner minCO2; + @FXML + private Spinner seuilCO2; + @FXML + private Spinner freqCO2; + @FXML + private Spinner maxTemp; + @FXML + private Spinner minTemp; + @FXML + private Spinner seuilTemp; + @FXML + private Spinner freqTemp; + @FXML + private Spinner maxHum; + @FXML + private Spinner minHum; + @FXML + private Spinner seuilHum; + @FXML + private Spinner freqHum; + @FXML + private ChoiceBox capteurCO2; + @FXML + private ChoiceBox capteurTemp; + @FXML + private ChoiceBox capteurHum; + @FXML + private TextField textserveur; + @FXML + private TextField textport; + + + /** + * Méthode initialize qui lance setConfig() + * */ + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + this.setConfig(); + } + + /** + * Méthode liée au bouton valider qui charge le fichier yml, créait une Map et ajoute chaque donnée saisie sur la page à l'intérieur + * pour ensuite écraser le contenu du fichier de config pour y mettre les nouvelles données qui sont dans la Map + * */ + public void actionValider(){ + //on charge le fichier de config dans la Map data + data = reader.chargerYaml(); + //on créait un nouveau Map pour stocker les nouvelles données + Map map = new HashMap<>(); + //on insère dans map les valeurs de la page de configuration + map.put("server",this.textserveur.getText()); + map.put("appId",this.textport.getText()); + //ici on récupère l'ancienne valeur (présente dans data) car on ne le changera jamais + map.put("deviceId",data.get("deviceId")); + map.put("tauxMaxCO2",this.maxCO2.getValue().toString()); + map.put("tauxMinCO2",this.minCO2.getValue().toString()); + map.put("seuilCO2",this.seuilCO2.getValue().toString()); + map.put("frequenceCO2",this.freqCO2.getValue().toString()); + map.put("tauxMaxTemp",this.maxTemp.getValue().toString()); + map.put("tauxMinTemp",this.minTemp.getValue().toString()); + map.put("seuilTemp",this.seuilTemp.getValue().toString()); + map.put("frequenceTemp",this.freqTemp.getValue().toString()); + map.put("tauxMaxHum",this.maxHum.getValue().toString()); + map.put("tauxMinHum",this.minHum.getValue().toString()); + map.put("seuilHum",this.seuilHum.getValue().toString()); + map.put("frequenceHum",this.freqHum.getValue().toString()); + map.put("capteurCO2",this.capteurCO2.getValue()); + map.put("capteurTemp",this.capteurTemp.getValue()); + map.put("capteurHum",this.capteurHum.getValue()); + try { + //une fois que toutes les données sont dans map on créait un PrintWriter vers le fichier config.yml pour ecraser son contenu + PrintWriter writer = new PrintWriter(new File("src/main/resources/app/appsae/config.yml")); + //on créait un nouveau yaml + Yaml yaml = new Yaml(); + //on dump dans le yaml les données de map dans le fichier config.yml + yaml.dump(map, writer); + }catch (Exception e){ + System.out.println("actionValider() : "+e.getMessage()); + System.exit(1); + } + + + } + + /** + * Méthode qui met les valeurs actuelles (du fichier de config) dans leur case pour les modifier + * */ + public void setConfig(){ + //on charge le fichier yml + data= reader.chargerYaml(); + //on créait les objets spinners pour y mettre des données Integer modifiable + SpinnerValueFactory spinnermaxco2= new SpinnerValueFactory.IntegerSpinnerValueFactory(Integer.parseInt(data.get("tauxMinCO2")),5000,Integer.parseInt(data.get("tauxMaxCO2"))); + //on lui donne ça valeur actuelle et on fais ça pour tous + this.maxCO2.setValueFactory(spinnermaxco2); + SpinnerValueFactory spinnerminco2= new SpinnerValueFactory.IntegerSpinnerValueFactory(0,Integer.parseInt(data.get("tauxMaxCO2")),Integer.parseInt(data.get("tauxMinCO2"))); + this.minCO2.setValueFactory(spinnerminco2); + SpinnerValueFactory spinnerseuilco2= new SpinnerValueFactory.IntegerSpinnerValueFactory(Integer.parseInt(data.get("tauxMinCO2")),Integer.parseInt(data.get("tauxMaxCO2")),Integer.parseInt(data.get("seuilCO2"))); + this.seuilCO2.setValueFactory(spinnerseuilco2); + SpinnerValueFactory spinnerfreqco2= new SpinnerValueFactory.IntegerSpinnerValueFactory(0,Integer.parseInt(data.get("tauxMaxCO2")),Integer.parseInt(data.get("frequenceCO2"))); + this.freqCO2.setValueFactory(spinnerfreqco2); + //ici on vide le menu déroulant des capteurs + this.capteurCO2.getItems().clear(); + //on remet les différents capteur (en brut..) + this.capteurCO2.getItems().addAll("AM107-7","AM107-3","AM107-9","AM107-4","AM107-2"); + //et on lui donne sa valeur actuelle + this.capteurCO2.setValue(String.valueOf(data.get("capteurCO2"))); + + //on fait la meme chose qu'au-dessus pour les éléments de température + SpinnerValueFactory spinnermaxtemp= new SpinnerValueFactory.IntegerSpinnerValueFactory(Integer.parseInt(data.get("tauxMinTemp")),200,Integer.parseInt(data.get("tauxMaxTemp"))); + this.maxTemp.setValueFactory(spinnermaxtemp); + SpinnerValueFactory spinnermintemp= new SpinnerValueFactory.IntegerSpinnerValueFactory(-50,Integer.parseInt(data.get("tauxMaxTemp")),Integer.parseInt(data.get("tauxMinTemp"))); + this.minTemp.setValueFactory(spinnermintemp); + SpinnerValueFactory spinnerseuiltemp= new SpinnerValueFactory.IntegerSpinnerValueFactory(Integer.parseInt(data.get("tauxMinTemp")),Integer.parseInt(data.get("tauxMaxTemp")),Integer.parseInt(data.get("seuilTemp"))); + this.seuilTemp.setValueFactory(spinnerseuiltemp); + SpinnerValueFactory spinnerfreqtemp= new SpinnerValueFactory.IntegerSpinnerValueFactory(0,Integer.parseInt(data.get("tauxMaxTemp")),Integer.parseInt(data.get("frequenceTemp"))); + this.freqTemp.setValueFactory(spinnerfreqtemp); + this.capteurTemp.getItems().clear(); + this.capteurTemp.getItems().addAll("AM107-7","AM107-3","AM107-9","AM107-4","AM107-2"); + this.capteurTemp.setValue(String.valueOf(data.get("capteurTemp"))); + + //encore la même chose pour les éléments d'humidité + SpinnerValueFactory spinnermaxhum= new SpinnerValueFactory.IntegerSpinnerValueFactory(Integer.parseInt(data.get("tauxMinHum")),200,Integer.parseInt(data.get("tauxMaxHum"))); + this.maxHum.setValueFactory(spinnermaxhum); + SpinnerValueFactory spinnerminhum= new SpinnerValueFactory.IntegerSpinnerValueFactory(-50,Integer.parseInt(data.get("tauxMaxHum")),Integer.parseInt(data.get("tauxMinHum"))); + this.minHum.setValueFactory(spinnerminhum); + SpinnerValueFactory spinnerseuilhum= new SpinnerValueFactory.IntegerSpinnerValueFactory(Integer.parseInt(data.get("tauxMinHum")),Integer.parseInt(data.get("tauxMaxHum")),Integer.parseInt(data.get("seuilHum"))); + this.seuilHum.setValueFactory(spinnerseuilhum); + SpinnerValueFactory spinnerfreqhum= new SpinnerValueFactory.IntegerSpinnerValueFactory(0,Integer.parseInt(data.get("tauxMaxHum")),Integer.parseInt(data.get("frequenceHum"))); + this.freqHum.setValueFactory(spinnerfreqhum); + this.capteurHum.getItems().clear(); + this.capteurHum.getItems().addAll("AM107-7","AM107-3","AM107-9","AM107-4","AM107-2"); + this.capteurHum.setValue(String.valueOf(data.get("capteurTemp"))); + + //ici on donne simplement leur valeur au textfield de serveur et port + this.textserveur.setText(data.get("server")); + this.textport.setText(data.get("appId")); + } + + /** + * Méthode qui initialise le stage actuel et qui lance actionQuitter si la croix rouge est cliquer sur se stage + * */ + public void setFenetrePrincipale(Stage st) { + //on change la valeur de la fenetreprincipale + this.fenetrePrincipale = st; + //on dit quoi faire quand la croix rouge est cliquée + this.fenetrePrincipale.setOnCloseRequest(e -> {e.consume();this.actionQuitter("quitter");}); + } + + + /** + * méthode liée au bouton quitter pour fermer la fenêtre ou pour valider le panneau de configuration + * */ + public void actionQuitter(String type) { + //un switch case qui sépare le cas valider et quitter + switch (type) { + //le cas quitter + case "quitter": + //pop up qui arrive quand on veut quitter + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Fermeture de l'application"); + alert.setHeaderText("Voulez vous vraiment quitter ?"); + alert.initOwner(fenetrePrincipale); + alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); + Optional response = alert.showAndWait(); + + //si oui on ferme la fenêtre + if (response.orElse(null) == ButtonType.YES) { + this.fenetrePrincipale.close(); + } + //cas de valider + case "valider": + //pop up pour valider la validation des informations + Alert alert2 = new Alert(Alert.AlertType.CONFIRMATION); + alert2.setTitle("Validation des informations"); + alert2.setHeaderText("Voulez vous vraiment valider (les informations ce mettront à jour) ?"); + alert2.initOwner(fenetrePrincipale); + alert2.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); + Optional response2 = alert2.showAndWait(); + + //si oui on appelle la méthode actionValider() et on ferme + if (response2.orElse(null) == ButtonType.YES) { + this.actionValider(); + this.fenetrePrincipale.close(); + } + } + } + + /** + * Méthode liée au bouton valider qui appelle la fonction actionQuitter(valider) + * */ + @FXML + public void actionValidation(){ + this.actionQuitter("valider"); + } +} diff --git a/Fichiers src IOT/Java src/AppSAE.java b/Fichiers src IOT/Java src/AppSAE.java new file mode 100644 index 00000000..78f01fa8 --- /dev/null +++ b/Fichiers src IOT/Java src/AppSAE.java @@ -0,0 +1,77 @@ +package app.appsae; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; + + + +/** + * Classe Application de mon code + * donc premier fichier à être lu et lance la première fenêtre + * */ +public class AppSAE extends Application { + + private Stage primaryStage; + private BorderPane rootPane; + + /** + * Main de l'app avec la méthode launch() qui va lancer la méthode start + * */ + public static void main(String[] args) { + launch(); + } + + /** + *Lance la première fenêtre de l'application + * */ + @Override + public void start(Stage stage){ + this.primaryStage = stage; + this.rootPane = new BorderPane(); + + Scene scene = new Scene(rootPane); + + //on paramètre la scène (titre, scene dans le stage et changement de taille impossible) + primaryStage.setTitle("Application capteur SubOne"); + primaryStage.setScene(scene); + primaryStage.setResizable(false); + + //on appelle la méthode App() + App(); + + + } + + /** + * Méthode utilisée pour lier le fxml à la fenêtre + * */ + public void App(){ + try { + //on charge le fichier fxml + FXMLLoader loader = new FXMLLoader(); + //on lui donne le chemin du fichier fxml + loader.setLocation(AppSAE.class.getResource("AppSAE.fxml")); + + //on charge le borderpane avec le fxml + BorderPane app = loader.load(); + + //on récupère le controller pour avoir accès à ses méthodes + AppSAEController ctrl = loader.getController(); + + //on utilise la méthode setFenetrePrincipale pour qu'on puisse fermer correctement la page + ctrl.setFenetrePrincipale(primaryStage); + + rootPane.setCenter(app); + + //on lance les méthodes initContext() et displayDialog() + ctrl.initContext(this.primaryStage); + ctrl.displayDialog(); + }catch (Exception e) { + System.out.println("App(): "+e.getMessage()); + System.exit(1); + } + } +} diff --git a/Fichiers src IOT/Java src/AppSAEController.java b/Fichiers src IOT/Java src/AppSAEController.java new file mode 100644 index 00000000..83f487c9 --- /dev/null +++ b/Fichiers src IOT/Java src/AppSAEController.java @@ -0,0 +1,266 @@ +package app.appsae; + +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.*; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; +import javafx.stage.Stage; +import java.net.URL; +import java.util.Map; +import java.util.Optional; +import java.util.ResourceBundle; + +/** + * Controller de la première scene + * */ +public class AppSAEController implements Initializable { + + private Stage fenetrePrincipale; + private ThreadMajGraph tmg; + final private Reader reader = new Reader(); + private Map data = reader.chargerYaml(); + + /** + * on donne à la variable fenetreprincipale la valeur du stage de la page + * */ + public void initContext(Stage primarystage){ + this.fenetrePrincipale = primarystage; + } + + /** + * Méthode qui affiche la fenêtre et lance le thread de mise à jour des graphiques + * */ + public void displayDialog() { + //on affiche la fenêtre actuelle + this.fenetrePrincipale.show(); + + // Création du "code" à exécuter en thread (un Runnable) + this.tmg = new ThreadMajGraph(this); + + // Création d'un thread pour exécuter notre code de rb (rb.run()) + Thread t = new Thread(this.tmg); + // Démarrage du thread + t.start(); + } + + @FXML + private StackedBarChart graphCO2; + @FXML + private StackedBarChart graphTEMP; + @FXML + private StackedBarChart graphHUM; + + @FXML + public NumberAxis yaxisco2; + @FXML + private NumberAxis yaxistemp; + @FXML + private NumberAxis yaxishum; + + /** + * Méthode de mise à jour du graphique de CO2 + * */ + public void majChartCO2(){ + try { + //on récupère les donnees du fichier txt (CO2) et les donnees de config + Map donneeco2 = reader.readerTXT("src/main/resources/app/appsae/co2.txt"); + data = reader.chargerYaml(); + + //on créait une nouvelle series + XYChart.Series srco2 = new StackedBarChart.Series(); + //on clear son contenu + srco2.getData().clear(); + //on créait une nouvelle series (pour le seuil de danger) + XYChart.Series srco2alert = new StackedBarChart.Series(); + //on clear son contenu + srco2alert.getData().clear(); + + //on ajoute des data dans les series en récupérant la donnée dans les Map (donneeco2 et data) + srco2.getData().add(new XYChart.Data<>("Actuel", Integer.parseInt(donneeco2.get(data.get("capteurCO2"))))); + srco2alert.getData().add(new XYChart.Data("Danger", Integer.parseInt(data.get("seuilCO2")))); + + //on clear le contenu du graph + graphCO2.getData().clear(); + //on y ajoute les deux nouvelles series + graphCO2.getData().add(srco2); + graphCO2.getData().add(srco2alert); + }catch (Exception e){ + System.out.println("majChartCO2(): "+e.getMessage()); + System.exit(1); + } + } + + /** + * Méthode qui configure le graphique de CO2 + * */ + public void initialisationParamGraphCO2(){ + //on choisit le titre du Yaxis + yaxisco2.setLabel("Niveau CO2"); + yaxisco2.setAutoRanging(false); + //on récupère le max et min du yaxis et on paramètre le graph avec elle + yaxisco2.setUpperBound(Integer.parseInt(data.get("tauxMaxCO2"))); + yaxisco2.setLowerBound(Integer.parseInt(data.get("tauxMinCO2"))); + // pareil avec le pas du graphique + yaxisco2.setTickUnit(Integer.parseInt(data.get("frequenceCO2"))); + //on retire la légende du graphique + graphCO2.setLegendVisible(false); + //on change la largeur des barres en mettant un espace entre elles + graphCO2.setCategoryGap(40); + graphCO2.setAnimated(false); + } + + /** + * Méthode de mise à jour du graphique de température + * */ + public void majChartTEMP(){ + try { + //on récupère les donnees du fichier txt (TEMP) et les donnees de config + Map donneetemp = reader.readerTXT("src/main/resources/app/appsae/temp.txt"); + data = reader.chargerYaml(); + + //on créait une nouvelle series + XYChart.Series srtemp = new StackedBarChart.Series(); + //on clear son contenu + srtemp.getData().clear(); + //on créait une nouvelle series (pour le seuil de danger) + XYChart.Series srtempalert = new StackedBarChart.Series(); + //on clear son contenu + srtempalert.getData().clear(); + + //on ajoute des data dans les series en récupérant la donnée dans les Map (donneeco2 et data) + srtemp.getData().add(new XYChart.Data<>("Actuel", Integer.parseInt(donneetemp.get(data.get("capteurTemp"))))); + srtempalert.getData().add(new XYChart.Data("Danger", Integer.parseInt(data.get("seuilTemp")))); + + //on clear le contenu du graph + graphTEMP.getData().clear(); + //on y ajoute les deux nouvelles series + graphTEMP.getData().add(srtemp); + graphTEMP.getData().add(srtempalert); + }catch (Exception e){ + System.out.println("majChartTEMP(): "+e.getMessage()); + System.exit(1); + } + } + /** + * Méthode qui configure le graphique de température + * */ + public void initialisationParamGraphTEMP(){ + //on choisit le titre du Yaxis + this.yaxistemp.setLabel("Niveau Température"); + this.yaxistemp.setAutoRanging(false); + //on récupère le max et min du yaxis et on paramètre le graph avec elle + this.yaxistemp.setUpperBound(Integer.parseInt(data.get("tauxMaxTemp"))); + this.yaxistemp.setLowerBound(Integer.parseInt(data.get("tauxMinTemp"))); + // pareil avec le pas du graphique + this.yaxistemp.setTickUnit(Integer.parseInt(data.get("frequenceTemp"))); + //on retire la légende du graphique + this.graphTEMP.setLegendVisible(false); + //on change la largeur des barres en mettant un espace entre elles + this.graphTEMP.setCategoryGap(40); + graphTEMP.setAnimated(false); + } + + /** + * Méthode de mise à jour du graphique d'humidité + * */ + public void majChartHUM(){ + try { + //on récupère les donnees du fichier txt (HUM) et les donnees de config + Map donneehum = reader.readerTXT("src/main/resources/app/appsae/hum.txt"); + data = reader.chargerYaml(); + + //on créait une nouvelle series + XYChart.Series srhum = new StackedBarChart.Series(); + //on clear son contenu + srhum.getData().clear(); + //on créait une nouvelle series (pour le seuil de danger) + XYChart.Series srhumalert = new StackedBarChart.Series(); + //on clear son contenu + srhumalert.getData().clear(); + + //on ajoute des data dans les series en récupérant la donnée dans les Map (donneeco2 et data) + srhum.getData().add(new XYChart.Data<>("Actuel", Integer.parseInt(donneehum.get(data.get("capteurHum"))))); + srhumalert.getData().add(new XYChart.Data("Danger", Integer.parseInt(data.get("seuilHum")))); + + //on clear le contenu du graph + graphHUM.getData().clear(); + //on y ajoute les deux nouvelles series + graphHUM.getData().add(srhum); + graphHUM.getData().add(srhumalert); + }catch (Exception e){ + System.out.println("majChartHUM(): "+e.getMessage()); + System.exit(1); + } + } + /** + * Méthode qui configure le graphique d'humidité + * */ + public void initialisationParamGraphHUM(){ + //on choisit le titre du Yaxis + this.yaxishum.setLabel("Niveau humidité"); + this.yaxishum.setAutoRanging(false); + //on récupère le max et min du yaxis et on paramètre le graph avec elle + this.yaxishum.setUpperBound(Integer.parseInt(data.get("tauxMaxHum"))); + this.yaxishum.setLowerBound(Integer.parseInt(data.get("tauxMinHum"))); + // pareil avec le pas du graphique + this.yaxishum.setTickUnit(Integer.parseInt(data.get("frequenceHum"))); + //on retire la légende du graphique + this.graphHUM.setLegendVisible(false); + //on change la largeur des barres en mettant un espace entre elles + this.graphHUM.setCategoryGap(40); + graphHUM.setAnimated(false); + } + + /** + * méthode qui initialise le stage actuel et qui lance actionQuitter si la croix rouge est cliqué sur ce stage + * */ + public void setFenetrePrincipale(Stage st) { + //on change la valeur de la fenetreprincipale + this.fenetrePrincipale = st; + //on dit quoi faire quand la croix rouge est cliqué + this.fenetrePrincipale.setOnCloseRequest(e -> {e.consume();this.actionQuitter();}); + } + + + /** + * méthode liée au bouton quitter pour fermer la fenêtre et arrêter le thread + */ + public void actionQuitter() { + //popup d'alerte pour être sûr de quitter + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Fermeture de l'application"); + alert.setHeaderText("Voulez vous vraiment quitter ?"); + alert.initOwner(fenetrePrincipale); + alert.getButtonTypes().setAll(ButtonType.YES,ButtonType.NO); + Optional response = alert.showAndWait(); + + // si la réponse est oui on close et on stop le thread + if (response.orElse(null)== ButtonType.YES) { + this.fenetrePrincipale.close(); + tmg.stop(); + } + } + + + /** + * méthode liée au bouton configuration qui lance la page de Configuration + * */ + public void actionConfig(){ + //on récupère le constructeur + AppConfig appConfig = new AppConfig(); + //on lance la methode start + appConfig.start(); + } + + /** + * méthode qui initialize les paramètres des graphiques en appelant ces méthodes + * */ + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + // on lance les trois méthodes pour initialiser les graphiques + this.initialisationParamGraphCO2(); + this.initialisationParamGraphTEMP(); + this.initialisationParamGraphHUM(); + } +} diff --git a/Fichiers src IOT/Java src/Reader.java b/Fichiers src IOT/Java src/Reader.java new file mode 100644 index 00000000..42b205d4 --- /dev/null +++ b/Fichiers src IOT/Java src/Reader.java @@ -0,0 +1,72 @@ +package app.appsae; + +import org.yaml.snakeyaml.Yaml; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +/** + * Classe permettant de lire les différents fichiers et de charger le fichier de config + * */ +public class Reader { + + /** + * Méthode qui lit les fichiers txt (co2, temp, hum) et les transforme en HashMap + * */ + public HashMap readerTXT(String pathfile){ + //on instancie le HashMap à remplir + HashMap dict = new HashMap<>(); + try { + //on créé un objet File qui prend comme valeur le fichier indiqué avec le pathfile + File file = new File(pathfile); + //On créé un FileReader avec file en paramètre + FileReader fr = new FileReader(file); + //On créé finalement un BufferedReader avec le FileReader en paramètre + BufferedReader bfr = new BufferedReader(fr); + + //on créait des variables qui nous seront utiles + String ligne; + String[] donnee; + + //on boucle (ici 10 fois) + for(int i=0;i<10;i++){ + //on lit la ligne + ligne = bfr.readLine(); + //on split la ligne en deux avec ; comme séparateur + donnee = ligne.split(";"); + //on ajoute le résultat dans le dictionnaire + dict.put(donnee[0],donnee[1]); + } + + }catch (Exception e){ + System.out.println("readerTXT(): "+e.getMessage()); + System.exit(1); + } + //on retourne le HashMap + return dict; + } + + /** + * Méthode qui charge un fichier yaml dans un Map + * */ + public Map chargerYaml(){ + //on créé notre Map qui est null pour l'instant + Map data = null; + + try { + // Créer un parseur de fichier yml + Yaml yaml = new Yaml(); + // Charger le fichier yml en mémoire + InputStream inputStream = new FileInputStream(new File("src/main/resources/app/appsae/config.yml")); + // Parser le fichier yml et récupérer les données dans un Map + data = yaml.load(inputStream); + + }catch (Exception e){ + System.out.println("chargerYaml(): "+e.getMessage()); + System.exit(1); + } + //on retourne le map + return data; + } +} diff --git a/Fichiers src IOT/Java src/ThreadMajGraph.java b/Fichiers src IOT/Java src/ThreadMajGraph.java new file mode 100644 index 00000000..67d96af6 --- /dev/null +++ b/Fichiers src IOT/Java src/ThreadMajGraph.java @@ -0,0 +1,61 @@ +package app.appsae; + +import javafx.application.Platform; + + +/** + * Classe pour le Thread de l'application implémentant Runnable + * */ +public class ThreadMajGraph implements Runnable{ + private boolean enCours; + private final AppSAEController ctrl; + + /** + * Constructeur de la classe qui prend on paramètre le controller AppSAEController + * */ + public ThreadMajGraph(AppSAEController asc) { + //on récupère le controller + this.ctrl = asc; + //on donne True comme valeur ici pour ensuite avoir la possibilité de créer une méthode stop + this.enCours = true; + } + + /** + * Méthode run de notre Thread + * */ + @Override + public void run() { + try { + //on boucle tant qu'on ne fait pas stop (donc tant que enCours = True) + while (enCours) { + //on utilise le Thread graphique Javafx + Platform.runLater(() -> { + //on lance les méthodes qui mettent à jour les graphiques + ThreadMajGraph.this.ctrl.majChartCO2(); + ThreadMajGraph.this.ctrl.majChartTEMP(); + ThreadMajGraph.this.ctrl.majChartHUM(); + }); + + System.out.println("RunBackground"); + try { + //on fait dormir le Thread pendant un duré (ici 10 seconde) + Thread.sleep(10000); + } catch (InterruptedException e) { + System.out.println("run1(): "+e.getMessage()); + System.exit(1); + } + } + }catch(Exception e){ + System.out.println("run2(): "+e.getMessage()); + System.exit(1); + } + } + + /** + * Méthode stop qui nous servira à arrêter le Thread + * */ + public void stop() { + //on passe la variable à False pour arrêter le Thread + this.enCours = false; + } +} diff --git a/Fichiers src IOT/Python src/main.py b/Fichiers src IOT/Python src/main.py new file mode 100644 index 00000000..8db639a4 --- /dev/null +++ b/Fichiers src IOT/Python src/main.py @@ -0,0 +1,143 @@ +import paho.mqtt.client as mqtt, json, yaml, os, sys, time, signal + +t=[] #tableau des températures +h=[] #tableau de l'humidite +c=[] #tableau du c02 + +#config +with open('config.yml', 'r') as fichier: + config=yaml.safe_load(fichier) + +#variables du fichier de config +server = config['server'] +appId = config['appId'] +deviceId = config['deviceId'] +tempM = config['tauxMaxTemp'] +c02M = config['tauxMaxC02'] +humM = config['tauxMaxHum'] +frequence = config['frequence'] + +tempMax = tempM.to_bytes(4, sys.byteorder) +c02Max = c02M.to_bytes(4, sys.byteorder) +humMax = humM.to_bytes(4, sys.byteorder) + +topic="application/{}/device/{}/event/up" + +def on_connect(client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + client.subscribe(topic.format(appId, deviceId)) + +def on_message(client, userdata, msg): + ft = os.open("./temperature.txt", os.O_WRONLY | os.O_CREAT | os.O_APPEND) #fichier des températures + fc = os.open("./c02.txt", os.O_WRONLY | os.O_CREAT | os.O_APPEND) #fichier des taux de c02 + fh = os.open("./humidite.txt", os.O_WRONLY | os.O_CREAT | os.O_APPEND) #fichier de % d'humidité + fs = os.open("./seuil.txt", os.O_WRONLY | os.O_CREAT | os.O_APPEND) #fichier des seuils d'alerte + global t + global h + global c + Jmsg=json.loads(msg.payload) + + #declaration des variables + name = Jmsg["deviceName"] + temp=Jmsg["object"]["temperature"] + hum=Jmsg["object"]["humidity"] + co2=Jmsg["object"]["co2"] + + #compteur par rapport à la fréquence choisie dans le fichier de configuration + signal.alarm(frequence) + +#méthode qui se lance à chaque fin de signal ou interception +def write(signum, code): + + #ecriture de la temperature, humidite et c02 dans les différents fichiers texte + nom = str(name) + nom_b = bytes(nom, 'utf-8') + + os.write(ft, b"\n") + os.write(fc, b"\n") + os.write(fh, b"\n") + os.write(fs, b"\n") + + os.write(ft, nom_b) + os.write(fc, nom_b) + os.write(fh, nom_b) + os.write(fs, nom_b) + + os.write(ft, b";") + os.write(fc, b";") + os.write(fh, b";") + os.write(fs, b";") + + #vérifications des données par rapport aux seuils max définis dans le fichier de configuration + temperature = str(temp) + temp_b = bytes(temperature, 'utf-8') + + if (temp_b > tempMax): + os.write(fs, temp_b) + os.write(fs, b";") + + else: + os.write(fs, b"-") + os.write(fs, b";") + os.write(ft, temp_b) + os.write(ft, b";") + + humidite = str(hum) + hum_b = bytes(humidite, 'utf-8') + + if (hum_b > humMax): + os.write(fs, hum_b) + os.write(fs, b";") + + else: + os.write(fs, b"-") + os.write(fs, b";") + os.write(fh, hum_b) + os.write(fh, b";") + + carbonasse = str(co2) + co2_b = bytes(carbonasse, 'utf-8') + + if (co2_b > c02Max): + os.write(fs, co2_b) + + else: + os.write(fs, b"-") + os.write(fs, b";") + os.write(fc, co2_b) + + #affichage dans le terminal + print(name) + print(temp, "°C") + t.append(temp) + print(t) + print(hum, "%") + h.append(hum) + print(h) + print(co2, "ppm") + c.append(co2) + print(c) + if len(t)>=10 : + print("Moyenne des températures = ",round(sum(t[-10:])/10,2), "°C") + if len(h)>=10 : + print("Moyenne de l'humidite = ",round(sum(h[-10:])/10,2), "%") + if len(c)>=10 : + print("Moyenne du co2 = ",round(sum(c[-10:])/10,2), "ppm") + + + + +client = mqtt.Client() + +#connexion au bus MQTT +client.on_connect = on_connect +client.connect(config['server'], 1883, 60) + +client.on_message = on_message + +#on lance la méthode d'écriture lorsque le signal alarm est reçu +signal.signal(signal.SIGALRM, write) +signal.alarm(frequence) + +#on boucle à l'infini le programme ci-dessus +client.loop_forever() \ No newline at end of file diff --git a/Fichiers src IOT/Python src/test.py b/Fichiers src IOT/Python src/test.py new file mode 100644 index 00000000..e9cc31f2 --- /dev/null +++ b/Fichiers src IOT/Python src/test.py @@ -0,0 +1,38 @@ +import paho.mqtt.client as mqtt, json, base64 + +# The callback for when the client receives a CONNACK response from the server. +def on_connect(client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + + # Subscribing in on_connect() means that if we lose the connection and + # reconnect then subscriptions will be renewed. + client.subscribe("application/1/device/+/event/up") + +# The callback for when a PUBLISH message is received from the server. +def on_message(client, userdata, msg): + Jmsg=json.loads(msg.payload) + mydata=Jmsg["object"] + if (mydata!=""): + print(mydata) + Jmydata=json.loads(mydata) + +#def bleu(): + # msg="blue" + # msg_bytes=msg.encode('ascii') + # b64_bytes=base64.b64encode(msg_bytes) + #b64_msg=b64_bytes.decode('ascii') + #print(b64_msg) + #payloadJson={"confirmed":False,"fPort":5,"data":b64_msg} + #client.publish(topic="application/1/device/0c7e450102030102/command/down",payload=json.dumps(payloadJson)) + +client = mqtt.Client() +client.on_connect = on_connect +client.on_message = on_message + +client.connect("chirpstack.iut-blagnac.fr", 1883, 60) + +# Blocking call that processes network traffic, dispatches callbacks and +# handles reconnecting. +# Other loop*() functions are available that give a threaded interface and a +# manual interface. +client.loop_forever() diff --git a/Fichiers src IOT/ressources/AppConfig.fxml b/Fichiers src IOT/ressources/AppConfig.fxml new file mode 100644 index 00000000..60901194 --- /dev/null +++ b/Fichiers src IOT/ressources/AppConfig.fxml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/Fichiers src IOT/ressources/AppSAE.fxml b/Fichiers src IOT/ressources/AppSAE.fxml new file mode 100644 index 00000000..0a75adf8 --- /dev/null +++ b/Fichiers src IOT/ressources/AppSAE.fxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/Fichiers src IOT/ressources/co2.txt b/Fichiers src IOT/ressources/co2.txt new file mode 100644 index 00000000..1739fe36 --- /dev/null +++ b/Fichiers src IOT/ressources/co2.txt @@ -0,0 +1,10 @@ +AM107-7;460 +AM107-3;641 +AM107-9;600 +AM107-4;728 +AM107-2;1600 +AM107-5;363 +AM107-8;487 +AM107-6;726 +AM107-11;471 +AM107-10;512 \ No newline at end of file diff --git a/Fichiers src IOT/ressources/config.yml b/Fichiers src IOT/ressources/config.yml new file mode 100644 index 00000000..b27b507d --- /dev/null +++ b/Fichiers src IOT/ressources/config.yml @@ -0,0 +1,4 @@ +{server: chirpstack.iut-blagnac.fr, seuilHum: '80', capteurHum: AM107-2, tauxMaxCO2: '2000', + capteurCO2: AM107-2, deviceId: +, tauxMinCO2: '0', seuilTemp: '60', tauxMaxHum: '100', + tauxMinHum: '0', appId: '1', tauxMaxTemp: '80', frequenceCO2: '100', frequenceTemp: '2', + frequenceHum: '1', capteurTemp: AM107-2, seuilCO2: '1200', tauxMinTemp: '0'} diff --git a/Fichiers src IOT/ressources/hum.txt b/Fichiers src IOT/ressources/hum.txt new file mode 100644 index 00000000..56514766 --- /dev/null +++ b/Fichiers src IOT/ressources/hum.txt @@ -0,0 +1,10 @@ +AM107-7;40 +AM107-3;45 +AM107-9;50 +AM107-4;35 +AM107-2;30 +AM107-5;25 +AM107-8;55 +AM107-6;60 +AM107-11;65 +AM107-10;20 \ No newline at end of file diff --git a/Fichiers src IOT/ressources/style.css b/Fichiers src IOT/ressources/style.css new file mode 100644 index 00000000..71a4fd73 --- /dev/null +++ b/Fichiers src IOT/ressources/style.css @@ -0,0 +1,4 @@ +.default-color0.chart-bar { -fx-bar-fill: GREEN +} +.default-color1.chart-bar { -fx-bar-fill: RED +} diff --git a/Fichiers src IOT/ressources/style2.css b/Fichiers src IOT/ressources/style2.css new file mode 100644 index 00000000..68e8d108 --- /dev/null +++ b/Fichiers src IOT/ressources/style2.css @@ -0,0 +1,4 @@ +.default-color0.chart-bar { -fx-bar-fill: PURPLE +} +.default-color1.chart-bar { -fx-bar-fill: RED +} diff --git a/Fichiers src IOT/ressources/style3.css b/Fichiers src IOT/ressources/style3.css new file mode 100644 index 00000000..732d874b --- /dev/null +++ b/Fichiers src IOT/ressources/style3.css @@ -0,0 +1,4 @@ +.default-color0.chart-bar { -fx-bar-fill: BLUE +} +.default-color1.chart-bar { -fx-bar-fill: RED +} diff --git a/Fichiers src IOT/ressources/temp.txt b/Fichiers src IOT/ressources/temp.txt new file mode 100644 index 00000000..6a69c8e4 --- /dev/null +++ b/Fichiers src IOT/ressources/temp.txt @@ -0,0 +1,10 @@ +AM107-7;24 +AM107-3;20 +AM107-9;21 +AM107-4;22 +AM107-2;23 +AM107-5;25 +AM107-8;19 +AM107-6;18 +AM107-11;15 +AM107-10;30 \ No newline at end of file diff --git a/Fichiers src site-web/Deconnexion.php b/Fichiers src site-web/Deconnexion.php new file mode 100644 index 00000000..bba17e94 --- /dev/null +++ b/Fichiers src site-web/Deconnexion.php @@ -0,0 +1,9 @@ + + alert("D\u00e9connexion effectu\u00e9e !"); + location.href = "./index.php"; + '; + +?> \ No newline at end of file diff --git a/Fichiers src site-web/GestionProduit.php b/Fichiers src site-web/GestionProduit.php new file mode 100644 index 00000000..19542869 --- /dev/null +++ b/Fichiers src site-web/GestionProduit.php @@ -0,0 +1,33 @@ + + + + + + + + + + + Gestion du stock + + + + + + + + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/Panier.php b/Fichiers src site-web/Panier.php new file mode 100644 index 00000000..274b534e --- /dev/null +++ b/Fichiers src site-web/Panier.php @@ -0,0 +1,173 @@ + + alert(" Filou, ce n\'est pas votre panier !"); + location.href = "index.php"; + '; +} + +?> + + + + + + + + + + Votre panier + + + + + + + + +
'; + + //si panier vide + + if (oci_fetch_assoc($panier) == false) { + echo '
Votre panier est vide !
+
'; + + } + + else { + + echo' +
Votre panier :
+ + + +
Prix du panier : '.$totalPanier.' €
+
+ +
'; } + + require_once('connect.inc.php'); + + // Affichage des produits du panier non-vide + + while (($article = oci_fetch_assoc($panier3)) != false) { + //$article = oci_fetch_assoc($panier); + + echo ' +
+ +
+ image du produit +
+ +
Nom de l\'article : '. $article['NOM'] .'
+ +
Quantité commandée : '. $article['NB'] . '
+ +
+ +
+ Quantité à retirer : + +
+ + +
+ +
'; + + } + + ?> + +
+ + + + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/Produit.php b/Fichiers src site-web/Produit.php new file mode 100644 index 00000000..24f04966 --- /dev/null +++ b/Fichiers src site-web/Produit.php @@ -0,0 +1,212 @@ + + + + + + + + + + + + Nos produits + + + +
+
+ + + + +
+
+ + +
+
+ Chercher un article : +
+ + + +
+ + + + +
+
Nos catégories : + + + + + + + +
+ +
+
+ + + +
+
+ +
Résultats pour :
+ +
+ +
+ Aucun résultat ...
'; + }*/ + + + + if (empty($res['IDARTICLE'])) { + echo'
Aucun résultat ...
'; + } + + else{ + // Affichage des produits + //$article = oci_fetch_assoc($articles); + //while (($article = oci_fetch_assoc($articles)) != false) { + for($i = 0; $i < count($res['IDARTICLE']); $i++){ + //foreach ($article as $article2) { //= oci_fetch_assoc($articles){ + echo ' +
+ +
+ image du produit +
+
'. $res['NOMARTICLE'][$i] .'
+ +
Catégorie : '. $res['NOMCATEGORIE'][$i] .'
+ + +
+ + '. $res['PRIXARTICLE'][$i] . '€ +
+ +
+ +
+ +
'; + + } + } + + + // lib�ration du curseur + oci_free_statement($articles); + ?> + +
+ + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/SupprCompte.php b/Fichiers src site-web/SupprCompte.php new file mode 100644 index 00000000..ceb94e41 --- /dev/null +++ b/Fichiers src site-web/SupprCompte.php @@ -0,0 +1,68 @@ + + alert(" Filou, ce n\'est pas votre compte !"); + location.href = "compteClient.php"; + '; +} + + +//on supprime le compte du client, ainsi que son panier et son contenu + +$reqSupprContenuPanier = "DELETE FROM DETAILPANIER WHERE IDPANIER = :pID_CLIENT"; + +$supprContenuPanier = oci_parse($connect, $reqSupprContenuPanier); + +oci_bind_by_name($supprContenuPanier, ":pID_CLIENT", $id); + +oci_execute($supprContenuPanier); + +oci_commit($connect); + +$reqSupprPanier = "DELETE FROM PANIER WHERE IDPANIER = :pID_CLIENT"; + +$supprPanier = oci_parse($connect, $reqSupprPanier); + +oci_bind_by_name($supprPanier, ":pID_CLIENT", $id); + +oci_execute($supprPanier); + +oci_commit($connect); + +$reqSupprClient = "DELETE FROM CLIENT WHERE IDCLIENT = :pID_CLIENT"; + +$supprClient = oci_parse($connect, $reqSupprClient); + +oci_bind_by_name($supprClient, ":pID_CLIENT", $id); + +oci_execute($supprClient); + +oci_commit($connect); + +$_SESSION['access']='NOT OK'; + +/*header("location: index.php"); +exit();*/ + +echo ''; + + +?> + \ No newline at end of file diff --git a/Fichiers src site-web/TraitCommande.php b/Fichiers src site-web/TraitCommande.php new file mode 100644 index 00000000..53d94e67 --- /dev/null +++ b/Fichiers src site-web/TraitCommande.php @@ -0,0 +1,234 @@ + + alert("Le nom n\'est pas similaire \u00e0 celui de votre compte !"); + location.href = "./commande.php"; + '; + } + + else if ($prenom != $_POST['prenom']){ + echo ''; + } + + else if(!preg_match($regex[0],$_POST['carte'])){ + echo ''; + } + + else if(!preg_match($regex[1],$_POST['date'])){ + echo ''; + } + + else if(!preg_match($regex[2],$_POST['ccv'])){ + echo ''; + } + + else { + + // on r�cup�re le prix du panier + + $reqPrix = "SELECT * FROM PANIER WHERE idPanier = :pID_CLIENT"; + + $prix = oci_parse($connect, $reqPrix); + + oci_bind_by_name($prix, ":pID_CLIENT", $idclient); + + oci_execute($prix); + + $panierprixtotal = oci_fetch_assoc($prix); + + $prixPanier = $panierprixtotal['PRIXPANIER']; + + +//----------------------------------------------------------// + + //on ajoute une ligne dans la table commande + + $req = "INSERT INTO COMMANDE VALUES (SEQIDCOMMANDE.NEXTVAL, :pID_CLIENT, :pPRIX)"; + + $req2 = oci_parse($connect, $req); + + oci_bind_by_name($req2, ":pID_CLIENT", $idclient); + oci_bind_by_name($req2, ":pPRIX", $prixPanier); + /*oci_bind_by_name($req2, ":pCARTE", $_POST['carte']); + oci_bind_by_name($req2, ":pCCV", $_POST['ccv']); + oci_bind_by_name($req2, ":pDATE", $_POST['date']);*/ + + oci_execute($req2); + + oci_commit($connect); + +//-----------------------------------------------------------------// + + //on ajoute le contenu de detailPanier dans detailCommande + + //on s�lectionne en premier l'idCommande qui vient d'�tre ajout� + + $reqId = "SELECT MAX(IDCOMMANDE) AS IDCOMMANDE FROM COMMANDE WHERE IDCLIENT = :pID_CLIENT"; + + $id = oci_parse($connect, $reqId); + + oci_bind_by_name($id, ":pID_CLIENT", $idclient); + /*oci_bind_by_name($id, ":pPRIX", $prixPanier); + oci_bind_by_name($id, ":pCARTE", $_POST['carte']); + oci_bind_by_name($id, ":pCCV", $_POST['ccv']); + oci_bind_by_name($id, ":pDATE", $_POST['date']);*/ + + oci_execute($id); + + $idComm = oci_fetch_assoc($id); + + $idCommande = $idComm['IDCOMMANDE']; //variable stockant l'id de la commande actuelle + + echo ''; + + + + //$idCommande = $idComm['IDCOMMANDE']; //variable stockant l'id de la commande actuelle + + //on prend ensuite tous les articles du panier du client + + $req3 = "SELECT * FROM DETAILPANIER WHERE IDPANIER = :pID_CLIENT"; + + $req4 = oci_parse($connect, $req3); + + oci_bind_by_name($req4, ":pID_CLIENT", $idclient); + + oci_execute($req4); + + //on ajoute enfin les articles du panier dans detailComande + + while (($articles = oci_fetch_assoc($req4)) != false) { + + $reqInsert = "INSERT INTO DETAILCOMMANDE VALUES (:pID_COMMANDE, :pID_ARTICLE, :pNB_ARTICLE)"; + + $insert = oci_parse($connect, $reqInsert); + + oci_bind_by_name($insert, ":pID_COMMANDE", $idCommande); //$idCommande + oci_bind_by_name($insert, ":pID_ARTICLE", $articles['IDARTICLE']); + oci_bind_by_name($insert, ":pNB_ARTICLE", $articles['NBARTICLE']); + + oci_execute($insert); + + oci_commit($connect); + + //on met � jour le stock de chaque article + $reqUpdate = "UPDATE ARTICLE SET QTESTOCK = QTESTOCK - :pNB_ARTICLE WHERE IDARTICLE = :pID_ARTICLE"; + + $update = oci_parse($connect, $reqUpdate); + + oci_bind_by_name($update, ":pNB_ARTICLE", $articles['NBARTICLE']); + oci_bind_by_name($update, ":pID_ARTICLE", $articles['IDARTICLE']); + + oci_execute($update); + + oci_commit($connect); + + } + +//-----------------------------------------------------------------// + + //on supprime le contenu du panier du client + + $req5 = "DELETE FROM DETAILPANIER WHERE IDPANIER = :pID_CLIENT"; + + $req6 = oci_parse($connect, $req5); + + oci_bind_by_name($req6, ":pID_CLIENT", $idclient); + + oci_execute($req6); + + oci_commit($connect); + +//-----------------------------------------------------------------// + + //apr�s avoir command�, si un des articles n'a plus de stock, on le supprime du panier de toutes les personnes l'ayant ajout� + + $reqPanierSuppr = "SELECT * FROM ARTICLE WHERE QTESTOCK = 0"; + + $panierSuppr = oci_parse($connect, $reqPanierSuppr); + + oci_execute($panierSuppr); + + while (($testSuppr = oci_fetch_assoc($panierSuppr)) != false){ + + $reqSupprimer = "DELETE FROM DETAILPANIER WHERE IDARTICLE = :pID_ARTICLE"; + + $supprimer = oci_parse($connect, $reqSupprimer); + + oci_bind_by_name($supprimer, ":pID_ARTICLE", $testSuppr['IDARTICLE']); + + oci_execute($supprimer); + + oci_commit($connect); + } + + + +//------------------------------------------------------------------------------ + + //enfin, on supprime le panier du client, puis retour � l'accueil + + $req7 = "DELETE FROM PANIER WHERE IDPANIER = :pID_CLIENT"; + + $req8 = oci_parse($connect, $req7); + + oci_bind_by_name($req8, ":pID_CLIENT", $idclient); + + oci_execute($req8); + + oci_commit($connect); + +//-----------------------------------------------------------------// + + //retour � l'accueil avec pop-up informatif + echo ''; + + } + } + + else { //si le filou tente de modifier l'url pour arriver direct sur cette page + echo ''; + } + + +?> \ No newline at end of file diff --git a/Fichiers src site-web/TraitConnexion.php b/Fichiers src site-web/TraitConnexion.php new file mode 100644 index 00000000..1e5df88e --- /dev/null +++ b/Fichiers src site-web/TraitConnexion.php @@ -0,0 +1,45 @@ + + alert("Mot de passe incorrect !"); + location.href = "./formulaireConnexion.php"; + '; + }else{ + $_SESSION['access']='OK'; + $_SESSION['prenom']=$mdp['PRENOMCLIENT']; + $_SESSION['nom']=$mdp['NOMCLIENT']; + $_SESSION['mailclient']= $mdp['EMAILCLIENT']; + $_SESSION['idclient']=$mdp['IDCLIENT']; + if (isset($_POST['cookie'])) { + $valCookie=$_POST['login']; + + // on met 60 sec de vie pour ce cookie afin de tester sa disparation + setcookie('cookIdent', $valCookie, time()+60); + } + header('location: index.php'); + exit(); + } + }else{ + echo ''; + } + oci_free_statement($compte); + } +?> diff --git a/Fichiers src site-web/TraitInscription.php b/Fichiers src site-web/TraitInscription.php new file mode 100644 index 00000000..95245933 --- /dev/null +++ b/Fichiers src site-web/TraitInscription.php @@ -0,0 +1,76 @@ + + alert("Le nom n\'est pas valide !"); + location.href = "./formulaireInscription.php"; + '; + } + else if(!preg_match($regex[0],$_POST['prenom'])){ + echo ''; + } + else if(!preg_match($regex[1],$_POST['email'])){ + echo ''; + } + else if (!preg_match($regex[2],$_POST['telephone'])){ + echo ''; + } + else if(!preg_match($regex[3],$_POST['motdepasse'])){ + echo ''; + }else{ + + require_once("connect.inc.php"); + error_reporting(0); + + $req2 = "INSERT INTO Client(idclient,nomclient,prenomclient,telclient,emailclient,mdpclient) + VALUES(SEQIDCLIENT.NEXTVAL,:pnom,:pprenom,:ptel,:pemail,:pmdp)"; + $insert = oci_parse($connect , $req2); + $nom = $_POST['nom']; + $prenom = $_POST['prenom']; + $tel = $_POST['telephone']; + $email = $_POST['email']; + $mdp = password_hash($_POST['motdepasse'], PASSWORD_DEFAULT); + oci_bind_by_name($insert, ":pnom", $nom); + oci_bind_by_name($insert, ":pprenom", $prenom); + oci_bind_by_name($insert, ":ptel", $tel); + oci_bind_by_name($insert, ":pemail", $email); + oci_bind_by_name($insert, ":pmdp", $mdp); + $result = oci_execute($insert); + + if (!$result) { + $e = oci_error($insert); // on récupère l'exception liée au pb d'éxecution de la requête (violation PK par exemple) + print htmlentities($e['message'].' pour cette requete : '.$e['sqltext']); + } + oci_commit($connect); + oci_free_statement($insert); + + echo ''; + //header("location: index.php"); //on revient à l'accueil + } + } +?> \ No newline at end of file diff --git a/Fichiers src site-web/TraitModif.php b/Fichiers src site-web/TraitModif.php new file mode 100644 index 00000000..0c46248f --- /dev/null +++ b/Fichiers src site-web/TraitModif.php @@ -0,0 +1,69 @@ + + alert("Le nom n\'est pas valide !"); + location.href = "./formulaireModif.php?pmail='.$_GET['email'].'"; + '; + } + else if(!preg_match($regex[0],$_POST['prenom'])){ + echo ''; + } + else if(!preg_match($regex[1],$_POST['email'])){ + echo ''; + } + else if (!preg_match($regex[2],$_POST['telephone'])){ + echo ''; + } + else if(!preg_match($regex[3],$_POST['motdepasse'])){ + echo ''; + }else{ + require_once("connect.inc.php"); + error_reporting(0); + $req4 = 'UPDATE Client SET nomclient=:pNom , prenomclient=:pPrenom , telclient=:ptel , emailclient=:pemail , + mdpclient=:pmdp WHERE emailclient=:ppemail'; + $update = oci_parse($connect , $req4); + $nom = $_POST['nom']; + $prenom = $_POST['prenom']; + $tel = $_POST['telephone']; + $email = $_POST['email']; + $email2 = htmlentities($_GET['email']); + $mdp = password_hash($_POST['motdepasse'], PASSWORD_DEFAULT); + oci_bind_by_name($update, ":pnom", $nom); + oci_bind_by_name($update, ":pprenom", $prenom); + oci_bind_by_name($update, ":ptel", $tel); + oci_bind_by_name($update, ":pemail", $email); + oci_bind_by_name($update, ":pmdp", $mdp); + oci_bind_by_name($update, ":ppemail", $email2); + $result = oci_execute($update); + if (!$result) { + $e = oci_error($update); // on récupère l'exception liée au pb d'execution de la requete + //(violation PK par exemple) + print htmlentities($e['message'].' pour cette requete : '.$e['sqltext']); + } + oci_commit($connect); + oci_free_statement($update); + header('location: index.php'); + } + } +?> \ No newline at end of file diff --git a/Fichiers src site-web/backrooms.html b/Fichiers src site-web/backrooms.html new file mode 100644 index 00000000..a49cb4c2 --- /dev/null +++ b/Fichiers src site-web/backrooms.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/Fichiers src site-web/commande.php b/Fichiers src site-web/commande.php new file mode 100644 index 00000000..5f4e357c --- /dev/null +++ b/Fichiers src site-web/commande.php @@ -0,0 +1,64 @@ + + + + + + + + + Commander + + + + + + + + + +

Vos informations de paiement :

+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+ + + + + ';?> +
+
Informations :
+

- Le nom & prénom renseignés doivent
être identiques à ceux de votre compte.

+ - Le numéro de carte ne doit pas contenir
d'espaces.

+ - La date d'expiration est du format 'MM/AA',
pensez à renseigner le '/'.

+ Nous ne conservons pas vos informations de paiement
dans notre base de données.

+
+ + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/commande2.php b/Fichiers src site-web/commande2.php new file mode 100644 index 00000000..6d1449b6 --- /dev/null +++ b/Fichiers src site-web/commande2.php @@ -0,0 +1,47 @@ + $nbReel){ + $test = $test + 1; + } +} + +if ($test == 0){ + + header('location: commande.php'); + exit(); +} + +else { + echo ''; +}*/ + +?> \ No newline at end of file diff --git a/Fichiers src site-web/compteClient.php b/Fichiers src site-web/compteClient.php new file mode 100644 index 00000000..7b699e95 --- /dev/null +++ b/Fichiers src site-web/compteClient.php @@ -0,0 +1,50 @@ + + + + + + + Compte client + + + + + + + + + + + + + + + + + '; + + + ?> + + + + diff --git a/Fichiers src site-web/connect.inc.php b/Fichiers src site-web/connect.inc.php new file mode 100644 index 00000000..eb464d7b --- /dev/null +++ b/Fichiers src site-web/connect.inc.php @@ -0,0 +1,16 @@ + diff --git a/Fichiers src site-web/consultCommandes.php b/Fichiers src site-web/consultCommandes.php new file mode 100644 index 00000000..62e9fc4a --- /dev/null +++ b/Fichiers src site-web/consultCommandes.php @@ -0,0 +1,101 @@ + + + + + + + + + + + Vos commandes + + + + + + + +
+ Vous n\'avez aucune commandes !
+
'; + } + + else { + + echo'
'; + + //while (($commande = oci_fetch_assoc($lesCommandes)) != false) { + for($i = 0; $i < count($res['IDCOMMANDE']); $i++){ + + $reqNbArticle = "SELECT SUM(NBARTICLE) AS NOMBRE FROM DETAILCOMMANDE WHERE IDCOMMANDE = :pID_COMMANDE "; + + $nbArticle = oci_parse($connect, $reqNbArticle); + + oci_bind_by_name($nbArticle, ":pID_COMMANDE", $res['IDCOMMANDE'][$i]); + + oci_execute($nbArticle); + + $nbArticleTotal = oci_fetch_assoc($nbArticle); + + $nb = $nbArticleTotal['NOMBRE']; + + echo '
+
Commande numéro '.$res['IDCOMMANDE'][$i].'
'; + if ($res['IDCOMMANDE'][$i]%2 == 0) { + echo' +
+ image satanique +
'; + }else{ + echo'
+ image satanique +
'; + } + + echo' + +
Prix de la commande : '.$res['PRIXTOTAL'][$i].' € +
+ +
Nombre d\'articles : '.$nb.'
+ + + +
'; + } + } + + +?> + +
+ + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/contacts.php b/Fichiers src site-web/contacts.php new file mode 100644 index 00000000..30686a20 --- /dev/null +++ b/Fichiers src site-web/contacts.php @@ -0,0 +1,44 @@ + + + + + + + + + Nous contacter + + + +
+ Nous contacter +
+ +
+
+
Notre bureau principal

+
12 Adresse du Beluga, Blagnac
+
+
+
Adresse mail

+
subone@gmail.com
+
+
+
Numéro de téléphone

+
(123) 456 7890
+
+
+
Réseaux sociaux

+
@subone (Twitter)
subone (Snapchat)
+
+
+ + + + + \ No newline at end of file diff --git a/Fichiers src site-web/detailArticle.php b/Fichiers src site-web/detailArticle.php new file mode 100644 index 00000000..87ffcd50 --- /dev/null +++ b/Fichiers src site-web/detailArticle.php @@ -0,0 +1,87 @@ + + + + + + + + Détail + + + + + 15 || htmlentities($_GET['idArticle']) <1 ) { + echo ''; +} + + +$req = "SELECT * FROM Article WHERE idArticle='".$_GET['idArticle']."'"; + +// pr�paration de la requ�te +$article = oci_parse($connect, $req); + +// ex�cution de la requ�te +oci_execute($article); + +$detail = oci_fetch_assoc($article); + + + + +$lesCategories = "SELECT * FROM Categorie C, Article A WHERE A.idCategorie = C.idCategorie AND A.idArticle = '".$_GET['idArticle']."'"; + +$cat = oci_parse($connect, $lesCategories); + +oci_execute($cat); + +$categorie = oci_fetch_assoc($cat); + +echo '
+
+ image du produit +
+
Nom de l\'article : '. $detail['NOMARTICLE'] .'
+ +
Catégorie : '. $categorie['NOMCATEGORIE'] .'
+ +
Quantité en stock : '. $detail['QTESTOCK'] .'
+ +
+ + Prix : '. $detail['PRIXARTICLE'] . '€ + +
+
Description : '. $detail['DESCRIPTIONARTICLE'] .'
+ +
+ Quantité à commander : + +
'; + + + + echo' + +
'; + + + // lib�ration du curseur + oci_free_statement($article); + +?> + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/detailCommande.php b/Fichiers src site-web/detailCommande.php new file mode 100644 index 00000000..1a7685f1 --- /dev/null +++ b/Fichiers src site-web/detailCommande.php @@ -0,0 +1,109 @@ + + + + + + + + Détail + + + + + +
+
+ + + alert(" Sacrebleu, ce n\'est pas votre commande !"); + location.href = "consultCommandes.php"; + '; +} + +//--------on affiche le détail de la commande en question ----------------// + +$reqDetail = "SELECT * FROM DETAILCOMMANDE WHERE IDCOMMANDE = :pID_COMMANDE"; + +$detail = oci_parse($connect, $reqDetail); + +oci_bind_by_name($detail, ":pID_COMMANDE", $detailCommande); + +oci_execute($detail); + +while (($article = oci_fetch_assoc($detail)) != false) { + + $idArticleEnfin = $article['IDARTICLE']; + + $reqAll = "SELECT * FROM ARTICLE WHERE IDARTICLE = '".$idArticleEnfin."'"; + + $all = oci_parse($connect, $reqAll); + + //oci_bind_by_name($connect, ":pID_ARTICLE", $idArticleEnfin); + + oci_execute($all); + + $article2 = oci_fetch_assoc($all); + + $prix = $article2['PRIXARTICLE']; + + $prixTotal = $prix * $article['NBARTICLE']; + + echo '
+
Article numéro '.$article['IDARTICLE'].'
+ +
+ image de l\'article +
+ + +
Prix unitaire : '.$prix.' € +
+ +
Nombre de fois commandé : '.$article['NBARTICLE'].'
+
Prix total : '.$prixTotal.' €
+ + +
'; + +} + + +?> + +
+
+ + + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/formulaireConnexion.php b/Fichiers src site-web/formulaireConnexion.php new file mode 100644 index 00000000..170d2291 --- /dev/null +++ b/Fichiers src site-web/formulaireConnexion.php @@ -0,0 +1,59 @@ + + + + + + + + + + Formulaire de connexion + + + + + + +
+ +
+ +

Veuillez vous

connecter

+
+ + > + Adresse e-mail + +
+
+ + Mot de passe + +
+ + + + + + + +
+
+ + + + \ No newline at end of file diff --git a/Fichiers src site-web/formulaireGestion1.php b/Fichiers src site-web/formulaireGestion1.php new file mode 100644 index 00000000..3e3e3a61 --- /dev/null +++ b/Fichiers src site-web/formulaireGestion1.php @@ -0,0 +1,82 @@ + + + + + + + + + + Ajouter du stock + + + + + + + +
Augmenter le stock d'un article
+ +
+ + + + + +
+ + + alert("'.$_POST['tentacles'].' article.s ajout\u00e9.s !"); + location.href = "GestionProduit.php"; + '; + + } + + ?> + + + + + + + diff --git a/Fichiers src site-web/formulaireGestion2.php b/Fichiers src site-web/formulaireGestion2.php new file mode 100644 index 00000000..56ff53e8 --- /dev/null +++ b/Fichiers src site-web/formulaireGestion2.php @@ -0,0 +1,107 @@ + + + + + + + + + + Retirer du stock + + + + + + + +
Baisser le stock d'un article
+ +
+ + + + + +
+ + + alert("Pas assez de stock de cet article pour en retirer '.$_POST['tentacles'].' ! ('.$stock.' en stock actuellement)"); + location.href = "formulaireGestion2.php"; + '; + exit(); + } + + //fin + + $procedure = "BEGIN RetraitArticle(:id, :stock); END;"; + + $proc = oci_parse($connect, $procedure); + + oci_bind_by_name($proc, ":id",$_POST["select"]); + + oci_bind_by_name($proc, ":stock",$_POST["tentacles"]); + + oci_execute($proc); + + oci_commit($connect); + + echo''; + } + + ?> + + + + + + diff --git a/Fichiers src site-web/formulaireInscription.php b/Fichiers src site-web/formulaireInscription.php new file mode 100644 index 00000000..a6648796 --- /dev/null +++ b/Fichiers src site-web/formulaireInscription.php @@ -0,0 +1,58 @@ + + + + + + + + + + Formulaire d'inscription + + + + + +
+ +
+ +

S'inscrire

+
+ + Nom + +
+
+ + Prénom + +
+
+ + Adresse mail + +
+
+ + Téléphone + +
+
+ + Mot de passe + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/Fichiers src site-web/formulaireModif.php b/Fichiers src site-web/formulaireModif.php new file mode 100644 index 00000000..4d094452 --- /dev/null +++ b/Fichiers src site-web/formulaireModif.php @@ -0,0 +1,73 @@ + + + + + + + + Modification compte + + + + + + alert(" Filou, ce n\'est pas votre compte !"); + location.href = "index.php"; + '; + } + + + $req3 = "SELECT * FROM Client WHERE emailclient = :pEmail"; + $compte = oci_parse($connect , $req3); + $email = $_GET['pmail']; + oci_bind_by_name($compte, ":pEmail", $email); + $result = oci_execute($compte); + $info = oci_fetch_assoc($compte); + + + + echo ' +
+ +
+ +

Modification

+
+ + Nom + +
+
+ + Prénom + +
+
+ + Adresse mail + +
+
+ + Téléphone + +
+
+ + Mot de passe + +
+ + +
+
'; + ?> + + + \ No newline at end of file diff --git a/Fichiers src site-web/hash_pwd.php b/Fichiers src site-web/hash_pwd.php new file mode 100644 index 00000000..de8b97fa --- /dev/null +++ b/Fichiers src site-web/hash_pwd.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/Fichiers src site-web/images/Beluga XL.png b/Fichiers src site-web/images/Beluga XL.png new file mode 100644 index 00000000..d6a6ef0a Binary files /dev/null and b/Fichiers src site-web/images/Beluga XL.png differ diff --git a/Fichiers src site-web/images/Beluga.png b/Fichiers src site-web/images/Beluga.png new file mode 100644 index 00000000..092ba153 Binary files /dev/null and b/Fichiers src site-web/images/Beluga.png differ diff --git a/Fichiers src site-web/images/Blue-J.png b/Fichiers src site-web/images/Blue-J.png new file mode 100644 index 00000000..caf828f1 Binary files /dev/null and b/Fichiers src site-web/images/Blue-J.png differ diff --git a/Fichiers src site-web/images/Cachalot.png b/Fichiers src site-web/images/Cachalot.png new file mode 100644 index 00000000..95108bed Binary files /dev/null and b/Fichiers src site-web/images/Cachalot.png differ diff --git a/Fichiers src site-web/images/Calmar.png b/Fichiers src site-web/images/Calmar.png new file mode 100644 index 00000000..d5d71cc3 Binary files /dev/null and b/Fichiers src site-web/images/Calmar.png differ diff --git a/Fichiers src site-web/images/Dauphin.png b/Fichiers src site-web/images/Dauphin.png new file mode 100644 index 00000000..b667e239 Binary files /dev/null and b/Fichiers src site-web/images/Dauphin.png differ diff --git a/Fichiers src site-web/images/Espadon.png b/Fichiers src site-web/images/Espadon.png new file mode 100644 index 00000000..48519509 Binary files /dev/null and b/Fichiers src site-web/images/Espadon.png differ diff --git a/Fichiers src site-web/images/Logo_SubOne_png.png b/Fichiers src site-web/images/Logo_SubOne_png.png new file mode 100644 index 00000000..a73f3aa8 Binary files /dev/null and b/Fichiers src site-web/images/Logo_SubOne_png.png differ diff --git a/Fichiers src site-web/images/Orque XL.png b/Fichiers src site-web/images/Orque XL.png new file mode 100644 index 00000000..a87e7783 Binary files /dev/null and b/Fichiers src site-web/images/Orque XL.png differ diff --git a/Fichiers src site-web/images/Orque.png b/Fichiers src site-web/images/Orque.png new file mode 100644 index 00000000..85919ec5 Binary files /dev/null and b/Fichiers src site-web/images/Orque.png differ diff --git a/Fichiers src site-web/images/Otarie.png b/Fichiers src site-web/images/Otarie.png new file mode 100644 index 00000000..2ff46495 Binary files /dev/null and b/Fichiers src site-web/images/Otarie.png differ diff --git a/Fichiers src site-web/images/Saumon.png b/Fichiers src site-web/images/Saumon.png new file mode 100644 index 00000000..11473ff8 Binary files /dev/null and b/Fichiers src site-web/images/Saumon.png differ diff --git a/Fichiers src site-web/images/Thon VR.png b/Fichiers src site-web/images/Thon VR.png new file mode 100644 index 00000000..36ee9ae5 Binary files /dev/null and b/Fichiers src site-web/images/Thon VR.png differ diff --git a/Fichiers src site-web/images/Thon.png b/Fichiers src site-web/images/Thon.png new file mode 100644 index 00000000..c43bd1c7 Binary files /dev/null and b/Fichiers src site-web/images/Thon.png differ diff --git a/Fichiers src site-web/images/detail.jpg b/Fichiers src site-web/images/detail.jpg new file mode 100644 index 00000000..6954124c Binary files /dev/null and b/Fichiers src site-web/images/detail.jpg differ diff --git a/Fichiers src site-web/images/fond_sous-marin.png b/Fichiers src site-web/images/fond_sous-marin.png new file mode 100644 index 00000000..e81b4c7d Binary files /dev/null and b/Fichiers src site-web/images/fond_sous-marin.png differ diff --git a/Fichiers src site-web/images/image_fond_client.png b/Fichiers src site-web/images/image_fond_client.png new file mode 100644 index 00000000..ed64eb2e Binary files /dev/null and b/Fichiers src site-web/images/image_fond_client.png differ diff --git a/Fichiers src site-web/images/leV.mp3 b/Fichiers src site-web/images/leV.mp3 new file mode 100644 index 00000000..687ed1be Binary files /dev/null and b/Fichiers src site-web/images/leV.mp3 differ diff --git a/Fichiers src site-web/images/leV.png b/Fichiers src site-web/images/leV.png new file mode 100644 index 00000000..7879b3f0 Binary files /dev/null and b/Fichiers src site-web/images/leV.png differ diff --git a/Fichiers src site-web/images/leo.jpg b/Fichiers src site-web/images/leo.jpg new file mode 100644 index 00000000..8f789d9e Binary files /dev/null and b/Fichiers src site-web/images/leo.jpg differ diff --git a/Fichiers src site-web/images/poubelle.png b/Fichiers src site-web/images/poubelle.png new file mode 100644 index 00000000..f715a36f Binary files /dev/null and b/Fichiers src site-web/images/poubelle.png differ diff --git a/Fichiers src site-web/images/rickroll.mp3 b/Fichiers src site-web/images/rickroll.mp3 new file mode 100644 index 00000000..0f539210 Binary files /dev/null and b/Fichiers src site-web/images/rickroll.mp3 differ diff --git a/Fichiers src site-web/images/sea.jpg b/Fichiers src site-web/images/sea.jpg new file mode 100644 index 00000000..d48bdbb5 Binary files /dev/null and b/Fichiers src site-web/images/sea.jpg differ diff --git a/Fichiers src site-web/images/sous-marin.png b/Fichiers src site-web/images/sous-marin.png new file mode 100644 index 00000000..82ccefff Binary files /dev/null and b/Fichiers src site-web/images/sous-marin.png differ diff --git a/Fichiers src site-web/images/v.jpg b/Fichiers src site-web/images/v.jpg new file mode 100644 index 00000000..ec1ff15f Binary files /dev/null and b/Fichiers src site-web/images/v.jpg differ diff --git a/Fichiers src site-web/include/Panier.css b/Fichiers src site-web/include/Panier.css new file mode 100644 index 00000000..3fd9a196 --- /dev/null +++ b/Fichiers src site-web/include/Panier.css @@ -0,0 +1,189 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +/*input[type="text"]{ + + border: 1px solid #111; + border-radius: 20px; + width: 150px; + height: 25px; + padding-left: 30px; + outline: none; + +}*/ + +.paniervide{ + +margin-top:100px; +padding-bottom : 23%; +font-size:50px; +text-align:center; +width:100%; +} + + +#vide{ +width : 150px; +height : 45px; + +} + +a{ + +text-decoration:none; +color : white; +font-family : Arial Black; +} + +html{ +background-color : #1AE2F9; +font-family:Poppins; +} + +/*.input { + + display:flex; + margin-top:10%; + margin-left:2%; + justify-content : flex-start; + gap:20px; +}*/ + +button{ + color : white; + font-family: Arial Black; + width:130px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + + +button:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} + + +.recherche{ + font-size : 15px; +} + +.produits{ + padding: 0 6%; +} + +.produit_header{ + margin-top: 100px; + display: flex; + gap : 30px; + justify-content: flex-start; + align-items: center; +} + +#retour{ +width : 180px; +height : 35px; +} + +#supprimer{ +width : 110px; +height : 35px; +} + +#supprimer2{ +width : 110px; +height : 35px; +} + +#supprimer2:hover{ +background-color: red; + border: 2px solid red; + cursor:pointer; +} + +#valider{ +width : 110px; +height : 35px; +} + +#supprimer:hover { + + background-color: red; + border: 2px solid red; + cursor:pointer; +} + +#valider:hover { + + background-color: green; + border: 2px solid green; + cursor:pointer; +} + +.produit_header .title{ + font-size: 30px; + font-weight: 500; +} + +.produit_container{ + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 50px; + margin-top: 60px; +} + +.card{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-bottom: 20px; + border-radius: 10px; + border : 2px solid #06395a; + background-color : #06f9f1; + +} + +.card .image img{ + width: 400px; + height: 400px; + object-fit: contain; + +} + +.card .title{ + font-size: 20px; + font-weight: 500; + margin-bottom: 10px; + margin-top: -20px; +} + +.card .nombre{ + color: #111; + font-weight: 500; + font-size: 20px; + margin-bottom: 30px; +} + + +.card .boutons{ + display: flex; + gap: 30px; +} + +/*#main { + min-height:100%; + position:relative; + padding-bottom:100px; +} +#footer { + position:absolute; + bottom:0; + width:100%; + height:100px; + background-color:black; + color : white; +}*/ diff --git a/Fichiers src site-web/include/caddie.png b/Fichiers src site-web/include/caddie.png new file mode 100644 index 00000000..45f211f9 Binary files /dev/null and b/Fichiers src site-web/include/caddie.png differ diff --git a/Fichiers src site-web/include/commande.css b/Fichiers src site-web/include/commande.css new file mode 100644 index 00000000..c023fb31 --- /dev/null +++ b/Fichiers src site-web/include/commande.css @@ -0,0 +1,97 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +html{ +background-color : #1AE2F9; +font-family:Poppins; + +} + +body { + display: flex; + justify-content: center; + align-items: center; +} + +form{ +margin-top: 8%; +text-decoration :none; + +border : 2px solid black; +border-radius : 20px; +padding : 30px; +display: flex; + flex-direction: column; + align-items: center; + gap : 10px; +} + +input { +height : 20px; +border-radius :20px; +padding : 10px; +width : 200px; +border : 2px solid grey; +} + +input:focus { +outline:none; +border : 2px solid black; +} + +input[type="submit"] { + color: white; + border-radius: 20px; + width: 150px; + font-family: Arial Black; + height: 48px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +input[type="submit"]:hover { + background-color : green; + cursor :pointer; + border: 2px solid green; + +} + +button { + color: white; + font-family: Arial Black; + width: 150px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + height: 48px; +} + +button:hover{ +background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} + +a{ +color:white; +text-decoration:none; +} + +p{ + text-align:justify; +} + +.infos{ + padding : 30px; + margin-top: 5%; + margin-left: 10px; +} + +.text{ + font-size:25px; + margin-left:70px; + text-decoration:underline; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/compteClient.css b/Fichiers src site-web/include/compteClient.css new file mode 100644 index 00000000..49e03829 --- /dev/null +++ b/Fichiers src site-web/include/compteClient.css @@ -0,0 +1,111 @@ +*{ + overflow: hidden; +} + +html{ + margin: 0; + height: 100%; +} +body{ + background-image:url(../images/image_fond_client.png); + background-size: cover; + background-position: top; + background-attachment: fixed; + position: inherit; + margin-top: 90px; + flex-direction:column; + display: flex; +} + +content{ + background-color: #60abbf; + width: 65%; + height: 550px; + display: flex; + flex-direction: column; + margin-left: auto; + margin-right: auto; + border-radius: 5%; +} + +#titre{ + width:100%; + height:fit-content; + text-align:center; + font-size: xx-large; + margin-top:2%; + font-family:Arial Black; + text-decoration:underline; + color: darkslategray; +} +.info{ + color: white; + margin-left: 15%; + margin-top: 4%; + font-size: x-large; + font-family: Arial; +} +#bouton{ + width: 100%; + font-size: inherit; + font-family: Arial; + color: white; + background-color: #06395a; + border-radius: 45px; + height: 30px; + transition-duration: 1s; + margin-top:20px; + border: 2px solid transparent; +} + +#haha{ + width: 100%; + font-size: inherit; + font-family: Arial; + color: white; + background-color: #06395a; + border-radius: 45px; + height: 30px; + transition-duration: 1s; + margin-top:20px; + border: 2px solid transparent; +} + + +#bouton2{ + width: 100%; + font-size: inherit; + font-family: Arial; + color: white; + background-color: #06395a; + border-radius: 45px; + height: 30px; + transition-duration: 1s; + border: 2px solid transparent; + margin-top:20px; +} + +#bouton:hover{ + transition-duration: 1s; + background-color: #fe7700; + cursor : pointer; +} + +#bouton2:hover{ + transition-duration: 1s; + background-color: red; + cursor : pointer; +} + +#haha:hover{ + transition-duration: 1s; + background-color: #fcbb00; + cursor : pointer; +} + +#lien{ + width:18%; + /*margin-top: 4%;*/ + margin-left: auto; + margin-right: auto; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/consultCommandes.css b/Fichiers src site-web/include/consultCommandes.css new file mode 100644 index 00000000..cb5747df --- /dev/null +++ b/Fichiers src site-web/include/consultCommandes.css @@ -0,0 +1,131 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +html { + background-color : #1AE2F9; + font-family:Poppins; + +} + +.container{ + display: grid; + grid-template-columns:repeat(2, 1fr); + gap: 50px; + margin-top: 60px; +} + +.card{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-bottom: 20px; + border-radius: 10px; + border : 2px solid #06395a; + background-color : #06f9f1; + +} + +.produit{ + padding: 0 6%; + margin-top:5%; +} + +.card .boutons{ + display: flex; + gap: 30px; +} + +.card .title{ + font-size: 30px; + font-weight: 500; + margin-bottom: 10px; + margin-top: 20px; +} + +#detail { + + color : white; + font-family: Arial Black; + width:130px; + height : 40px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; +} + +#detail:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} + +a{ + text-decoration:none; + color:white; +} + +.card .image img{ + width: 350px; + height: 400px; + /*object-fit: contain;*/ + border-radius : 20px; + +} + +.no_commandes{ + +margin-top:100px; +padding-bottom : 23%; +font-size:50px; +text-align:center; +width:100%; +} + + +.no_commandes button{ +width : 150px; +height : 50px; +color : white; + font-family: Arial Black; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +.no_commandes button:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} + +.paniervide{ + +margin-top:100px; +padding-bottom : 23%; +font-size:50px; +text-align:center; +width:100%; +} + + +#vide{ + +height : 50px; +color : white; + font-family: Arial Black; + width:150px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +#vide:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} diff --git a/Fichiers src site-web/include/contact.css b/Fichiers src site-web/include/contact.css new file mode 100644 index 00000000..797759f2 --- /dev/null +++ b/Fichiers src site-web/include/contact.css @@ -0,0 +1,51 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + overflow:hidden; +} + +body { + font-family: 'Poppins', sans-serif; + background-color: #FFA533; + overflow:hidden; + display:flex; + flex-direction:column; +} + + +.titre{ + font-size: 50px; + margin-left: 50px; + padding-top:9%; +} + +.title { + color: white; + font-size: 30px; + text-align: center; +} + +.content { + color: #337FFF; + font-size: 20px; + text-align: center; +} + + +.container { + display: grid; + grid-template-columns: repeat(2, 1fr); + justify-items: center; + align-items: center; + width: 100%; + height: 100%; + margin-top:1%; + +} + +.box{ + + width: 300px; + height: 200px; + padding: 20px; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/detailArticle.css b/Fichiers src site-web/include/detailArticle.css new file mode 100644 index 00000000..ea4c96bb --- /dev/null +++ b/Fichiers src site-web/include/detailArticle.css @@ -0,0 +1,149 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +body{ + + background-image:url(../images/detail.jpg); + background-size: cover; + background-position: top; + background-attachment: fixed; + position: inherit; + flex-direction:column; + display: flex; + margin:0; +} + +.card{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-bottom: 20px; + border-radius: 10px; + border : 2px solid black; + margin-top:8%; + width : 50%; + margin-left:25%; + background-color:#1AE2F9; + +} + +.card .image img{ + width: 400px; + height: 400px; + object-fit: contain; + border-radius:20px; + +} +.card .title{ + font-size: 20px; + font-family : Poppins; + margin-bottom: 10px; + margin-top: -20px; +} + +.card .categorie{ + font-size: 20px; + font-family : Poppins; + margin-bottom: 10px; + margin-top: 5px; +} + +.card .stock{ + font-size: 20px; + font-family : Poppins; + margin-bottom: 10px; + margin-top: 5px; +} + +.card .desc{ + padding-left:20px; + padding-right:20px; + font-family : Poppins; + margin-bottom:20px; + +} + +.card .prix{ + font-size: 20px; + margin-bottom: 10px; + font-family : Poppins; +} + +button{ + + color : white; + font-family: Arial Black; + width:130px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + height : 50px; +} + + +button:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; + +} + +.boutons { +display:flex; +gap:50px; + +} + +a{ + +text-decoration:none; +color : white; +font-family : Arial Black; +} + +form{ +font-family : Poppins; +margin-bottom: 20px; +font-size:20px; +gap : 20px; +display : flex; +} + +input[type="number"]{ +border-radius : 20px; +padding-left: 10px; +padding-right: 20px; +width : 80px; +height : 30px; + +} + +input[type="number"]:focus{ +outline : none; +} + +input[type="submit"]{ + +color : white; +border-radius : 20px; +width : 150px; +font-family: Arial Black; +height : 40px; +transition-duration: 0.5s; +background-color: #06395a; +border: 2px solid #06395a; +border-radius: 45px; + +} + +input[type="submit"]:hover{ + +background-color: green; +color : white; +border: 2px solid green; +cursor:pointer; +} + + + diff --git a/Fichiers src site-web/include/detailCommande.css b/Fichiers src site-web/include/detailCommande.css new file mode 100644 index 00000000..b044ec4a --- /dev/null +++ b/Fichiers src site-web/include/detailCommande.css @@ -0,0 +1,73 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +html { + background-image:url(../images/detail.jpg); + font-family:Poppins; + background-attachment : fixed; + +} + + +.container{ + display: grid; + grid-template-columns:repeat(2, 1fr); + gap: 50px; + margin-top: 60px; +} + +.card{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-bottom: 20px; + border-radius: 10px; + border : 2px solid #06395a; + background-color : #06f9f1; + +} + +.produit{ + padding: 0 6%; + margin-top:5%; +} + +.card .title{ + font-size: 30px; + font-weight: 500; + margin-bottom: -20px; + margin-top: 20px; +} + +.card .image img{ + width: 400px; + height: 400px; + object-fit: contain; + border-radius : 20px; + +} + +a{ + text-decoration:none; + color:white; +} + +#retour { + + color : white; + font-family: Arial Black; + width:100%; + height : 50px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + margin-top : 20px; + border-color:#06f9f1; +} + +#retour:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/footer.css b/Fichiers src site-web/include/footer.css new file mode 100644 index 00000000..5d49ae00 --- /dev/null +++ b/Fichiers src site-web/include/footer.css @@ -0,0 +1,20 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + overflow-x : hidden +} + + +.footer{ + width:100%; + background-color: black; + height : 50px; + text-align:center; + font-family: 'Poppins'; + color: white; + font-size: larger; + bottom:0; + position:absolute; + left: 0; + padding-top:20px; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/footer.php b/Fichiers src site-web/include/footer.php new file mode 100644 index 00000000..580cab7d --- /dev/null +++ b/Fichiers src site-web/include/footer.php @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/Fichiers src site-web/include/footer2.css b/Fichiers src site-web/include/footer2.css new file mode 100644 index 00000000..dfe44ca3 --- /dev/null +++ b/Fichiers src site-web/include/footer2.css @@ -0,0 +1,20 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + overflow-x : hidden +} + +.footer{ + width:100%; + background-color: black; + height : 50px; + text-align:center; + font-family: 'Poppins'; + color: white; + font-size: larger; + bottom:0; + position:sticky; + left: 0; + padding-top:20px; + margin-top:20px; +} diff --git a/Fichiers src site-web/include/footer2.php b/Fichiers src site-web/include/footer2.php new file mode 100644 index 00000000..db4cd6cb --- /dev/null +++ b/Fichiers src site-web/include/footer2.php @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Fichiers src site-web/include/footer3.css b/Fichiers src site-web/include/footer3.css new file mode 100644 index 00000000..28093e81 --- /dev/null +++ b/Fichiers src site-web/include/footer3.css @@ -0,0 +1,20 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + overflow-x : hidden +} + +.footer{ + width:100%; + background-color: black; + height : 70px; + text-align:center; + font-family: 'Poppins'; + color: white; + font-size: larger; + bottom:0; + position:absolute; + left: 0; + padding-top:20px; + margin-top:20px; +} diff --git a/Fichiers src site-web/include/footer3.php b/Fichiers src site-web/include/footer3.php new file mode 100644 index 00000000..6c1edcf4 --- /dev/null +++ b/Fichiers src site-web/include/footer3.php @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Fichiers src site-web/include/formulaire.css b/Fichiers src site-web/include/formulaire.css new file mode 100644 index 00000000..094eee0f --- /dev/null +++ b/Fichiers src site-web/include/formulaire.css @@ -0,0 +1,180 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + margin : 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; + text-decoration: none; + color : grey; + overflow: hidden; +} + +p{ + color: yellow; +} + +body{ + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background: #23242a; + background-image: url("../images/sea.jpg"); +} + +.box{ + position: relative; + width: 380px; + height: 540px; + background: #1c1c1c; + border-radius: 8px; + overflow: hidden; +} + +.box::before{ + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 380px; + height: 420px; + background: linear-gradient(0deg, transparent, #45f3ff, #45f3ff); + animation: animate 6s linear infinite; + transform-origin: bottom right; +} + +.box::after{ + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 380px; + height: 420px; + background: linear-gradient(0deg, transparent, yellow, yellow); + animation: animate 6s linear infinite; + transform-origin: bottom right; + animation-delay: -3s; +} + +@keyframes animate { + 0% + { + transform: rotate(0deg); + } + 100% + { + transform: rotate(360deg); + } + +} + +.form { + position: absolute; + inset: 2px; + border-radius: 8px; + background: #28292d; + z-index: 10; + padding: 50px 40px; + display: flex; + flex-direction: column; + +} + +.form h2{ + color: #45f3ff; + font-weight: 500; + text-align: center; + letter-spacing: .1em; + height: 70px; +} + +.inputBox{ + position: relative; + width: 300px; + margin-top: 35px; +} + +.inputBox input{ + position: relative; + width: 100%; + padding: 20px 10px 10px; + background: transparent; + border: none; + outline: none; + color: #23242a; + font-size: 1em; + letter-spacing: .05em; + z-index: 10; +} + +.inputBox span{ + position: absolute; + left: 0; + padding: 20px 10px 10px; + font-size: 1em; + color: #8f8f8f; + pointer-events: none; + letter-spacing: .05em; + transition: .5s; +} + +.inputBox input:valid ~ span, +.inputBox input:focus ~ span{ + color: #45f3ff; + transform: translateY(-34px); + font-size: .75em; +} + +.inputBox i{ + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background: #45f3ff; + border-radius: 4px; + transition: .5s; + pointer-events: none; + z-index: 9; +} + +.inputBox input:valid ~ i, +.inputBox input:focus ~ i{ + height: 44px; +} + +input[type="submit"]{ + border: none; + outline: none; + background: #45f3ff; + padding: 11px 25px; + width: 140px; + margin-top: 35px; + margin-left: 25%; + border-radius: 4px; + font-weight: 600; + cursor: pointer; + color : black; +} + +input[type="submit"]:active{ + opacity: 0.8; +} + +.link{ + display: flex; + font-size: 70%; + margin-left: 10px; + padding-top : 20px; + color : #8f8f8f; + position: relative; +} + +.link :hover{ + color:white; +} + +.cookie{ + margin-top:50px; +} diff --git a/Fichiers src site-web/include/formulaire2.css b/Fichiers src site-web/include/formulaire2.css new file mode 100644 index 00000000..dd3730c9 --- /dev/null +++ b/Fichiers src site-web/include/formulaire2.css @@ -0,0 +1,162 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + margin : 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; + text-decoration: none; + color : grey; + overflow: hidden; + +} + +p{ + color: yellow; +} + +body{ + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background: #23242a; + background-image: url("../images/sea.jpg"); +} + +.box{ + position: relative; + width: 380px; + height: 550px; + background: #1c1c1c; + border-radius: 8px; + overflow: hidden; +} + +.box::before{ + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 380px; + height: 680px; + background: linear-gradient(0deg, transparent, #45f3ff, #45f3ff); + animation: animate 6s linear infinite; + transform-origin: bottom right; +} + +.box::after{ + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 380px; + height: 520px; + background: linear-gradient(0deg, transparent, yellow, yellow); + animation: animate 6s linear infinite; + transform-origin: bottom right; + animation-delay: -3s; +} + +@keyframes animate { + 0% + { + transform: rotate(0deg); + } + 100% + { + transform: rotate(360deg); + } +} + +.form { + position: absolute; + inset: 2px; + border-radius: 8px; + background: #28292d; + z-index: 10; + padding: 20px 40px; + display: flex; + flex-direction: column; + +} + +.form h2{ + color: #45f3ff; + font-weight: 500; + text-align: center; + letter-spacing: .1em; +} + +.inputBox{ + position: relative; + width: 300px; + margin-top: 35px; +} + +.inputBox input{ + position: relative; + width: 100%; + padding: 20px 10px 10px; + background: transparent; + border: none; + outline: none; + color: #23242a; + font-size: 1em; + letter-spacing: .05em; + z-index: 10; +} + +.inputBox span{ + position: absolute; + left: 0; + padding: 20px 10px 10px; + font-size: 1em; + color: #8f8f8f; + pointer-events: none; + letter-spacing: .05em; + transition: .5s; +} + +.inputBox input:valid ~ span, +.inputBox input:focus ~ span{ + color: #45f3ff; + transform: translateY(-34px); + font-size: .75em; +} + +.inputBox i{ + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background: #45f3ff; + border-radius: 4px; + transition: .5s; + pointer-events: none; + z-index: 9; +} + +.inputBox input:valid ~ i, +.inputBox input:focus ~ i{ + height: 44px; +} + +input[type="submit"]{ + border: none; + outline: none; + background: #45f3ff; + padding: 11px 25px; + width: 180px; + margin-top: 35px; + margin-left: 20%; + border-radius: 4px; + font-weight: 600; + cursor: pointer; + color : black; +} + +input[type="submit"]:active{ + opacity: 0.8; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/formulaire3.css b/Fichiers src site-web/include/formulaire3.css new file mode 100644 index 00000000..dd3730c9 --- /dev/null +++ b/Fichiers src site-web/include/formulaire3.css @@ -0,0 +1,162 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + margin : 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; + text-decoration: none; + color : grey; + overflow: hidden; + +} + +p{ + color: yellow; +} + +body{ + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background: #23242a; + background-image: url("../images/sea.jpg"); +} + +.box{ + position: relative; + width: 380px; + height: 550px; + background: #1c1c1c; + border-radius: 8px; + overflow: hidden; +} + +.box::before{ + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 380px; + height: 680px; + background: linear-gradient(0deg, transparent, #45f3ff, #45f3ff); + animation: animate 6s linear infinite; + transform-origin: bottom right; +} + +.box::after{ + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 380px; + height: 520px; + background: linear-gradient(0deg, transparent, yellow, yellow); + animation: animate 6s linear infinite; + transform-origin: bottom right; + animation-delay: -3s; +} + +@keyframes animate { + 0% + { + transform: rotate(0deg); + } + 100% + { + transform: rotate(360deg); + } +} + +.form { + position: absolute; + inset: 2px; + border-radius: 8px; + background: #28292d; + z-index: 10; + padding: 20px 40px; + display: flex; + flex-direction: column; + +} + +.form h2{ + color: #45f3ff; + font-weight: 500; + text-align: center; + letter-spacing: .1em; +} + +.inputBox{ + position: relative; + width: 300px; + margin-top: 35px; +} + +.inputBox input{ + position: relative; + width: 100%; + padding: 20px 10px 10px; + background: transparent; + border: none; + outline: none; + color: #23242a; + font-size: 1em; + letter-spacing: .05em; + z-index: 10; +} + +.inputBox span{ + position: absolute; + left: 0; + padding: 20px 10px 10px; + font-size: 1em; + color: #8f8f8f; + pointer-events: none; + letter-spacing: .05em; + transition: .5s; +} + +.inputBox input:valid ~ span, +.inputBox input:focus ~ span{ + color: #45f3ff; + transform: translateY(-34px); + font-size: .75em; +} + +.inputBox i{ + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background: #45f3ff; + border-radius: 4px; + transition: .5s; + pointer-events: none; + z-index: 9; +} + +.inputBox input:valid ~ i, +.inputBox input:focus ~ i{ + height: 44px; +} + +input[type="submit"]{ + border: none; + outline: none; + background: #45f3ff; + padding: 11px 25px; + width: 180px; + margin-top: 35px; + margin-left: 20%; + border-radius: 4px; + font-weight: 600; + cursor: pointer; + color : black; +} + +input[type="submit"]:active{ + opacity: 0.8; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/formulaireGestion1.css b/Fichiers src site-web/include/formulaireGestion1.css new file mode 100644 index 00000000..48d098ce --- /dev/null +++ b/Fichiers src site-web/include/formulaireGestion1.css @@ -0,0 +1,98 @@ +*{ + margin : 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; + text-decoration: none; + color : grey; + overflow: hidden; +} + +body{ + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background: #23242a; + background-image: url("../images/sea.jpg"); +} +.form1{ + border: 0; + font-size: 3em; + border: 3px solid rgb(5, 30, 53); + border-style: double; + border-radius: 15px; + padding: 20px; + margin-top : -100px; + display: flex; + gap: 20px; + align-items: center; +} + +.lab{ + color : #06395a; + font-weight : bold; + +} + +input[type="submit"] { + color: white; + border-radius: 20px; + width: 110px; + font-family: Arial Black; + height: 48px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +input[type="submit"]:hover { + background-color : green; + cursor :pointer; + border: 2px solid green; + +} + +select:hover{ + cursor:pointer; +} + +input[type="number"]{ +border-radius : 20px; +padding-left: 10px; +padding-right: 20px; +width : 80px; +height : 30px; +padding-top:1px; + +} + +input[type="number"]:focus{ +outline : none; +} + +#retour{ + position: absolute; + margin-top: 10%; + color: white; + border-radius: 20px; + width: 150px; + font-family: Arial Black; + height: 48px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; +} + +#retour:hover{ + background-color : #fcbb00; + cursor :pointer; + border: 2px solid #fcbb00; +} + +a{ + color:white; +} \ No newline at end of file diff --git a/Fichiers src site-web/include/formulaireGestion2.css b/Fichiers src site-web/include/formulaireGestion2.css new file mode 100644 index 00000000..f7146208 --- /dev/null +++ b/Fichiers src site-web/include/formulaireGestion2.css @@ -0,0 +1,33 @@ +*{ + margin : 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; + text-decoration: none; + color : grey; + overflow: hidden; +} + +body{ + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background: #23242a; + background-image: url("../images/sea.jpg"); +} +.form1{ + border: 0; + font-size: 3em; + border: 3px solid rgb(5, 30, 53); + border-style: double; + border-radius: 15px; + padding: 12px 45px; + font-family : "Times New Roman", Times, serif; +} +.lab{ + color : #fff; + font-family : "Times New Roman", Times, serif; + font-weight : bold; + +} diff --git a/Fichiers src site-web/include/gestionpro.css b/Fichiers src site-web/include/gestionpro.css new file mode 100644 index 00000000..67a7ce74 --- /dev/null +++ b/Fichiers src site-web/include/gestionpro.css @@ -0,0 +1,45 @@ +*{ + margin : 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; + text-decoration: none; + /*color : grey;*/ + overflow: hidden; +} + +body { + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background: #23242a; + background-image: url("../images/sea.jpg"); +} + +#b1, #b2{ + color : white; + font-family: Arial Black; + width:140px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + height : 50px; +} + +#b1:hover{ + background-color: green; + border: 2px solid green; + cursor:pointer; +} + +#b2:hover{ + background-color: red; + border: 2px solid red; + cursor:pointer; +} + +a{ + color:white; +} diff --git a/Fichiers src site-web/include/header.css b/Fichiers src site-web/include/header.css new file mode 100644 index 00000000..7b3997b1 --- /dev/null +++ b/Fichiers src site-web/include/header.css @@ -0,0 +1,55 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +header{ + display:flex; + justify-content: space-between; + height: 100px; + width:100%; + top:0; + position:absolute; +} + + + +#logo{ + height:90%; +} + +bouton{ + width:60%; + display:flex; + justify-content: space-between; + float: right; + padding-top: 20px; + padding-right : 20px; +} + +.bouton{ + width:200px; + height:50px; + align-content:center; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; +} + +.bouton:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} + +.bouton:active{ + background-color: #fcbb00; + border : 2px solid black +} + +#bouton1{ + color:white; + font-size: 20px; + font-style: bold; + font-family:Arial Black; +} + + diff --git a/Fichiers src site-web/include/header.php b/Fichiers src site-web/include/header.php new file mode 100644 index 00000000..e541fed8 --- /dev/null +++ b/Fichiers src site-web/include/header.php @@ -0,0 +1,36 @@ + +
+ + + + + + + + + '; + }else { + + echo ' + '; + } + + + + echo' + + '; + + + ?> + + +
\ No newline at end of file diff --git a/Fichiers src site-web/include/index.css b/Fichiers src site-web/include/index.css new file mode 100644 index 00000000..af5dfd02 --- /dev/null +++ b/Fichiers src site-web/include/index.css @@ -0,0 +1,82 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +*{ + overflow:hidden; +} + +html{ + margin: 0; + height: 100%; +} +body{ + background-image:url(../images/fond_sous-marin.png); + background-size: cover; + background-position: top; + background-attachment: fixed; + height: auto; + flex-direction : column; + display:flex; +} + +#divtitre{ + justify-content: space-between; + display:flex; + width: 100%; + height:auto; + position: absolute; + bottom: 6%; +} + +.text{ + color:white; + font-size: 110px; + font-family:Arial Black; + padding-left:2%; +} + +.bonjour{ + font-family: Poppins; + margin-top: 10%; + margin-left: 2%; + color: white; + font-weight: 500; + font-size: 40px; + +} + +label1{ + width:70%; +} + +bouton2{ + padding-right:2%; + padding-bottom:2%; + display:flex; + width:25%; +} + +.bouton2{ + width:150px; + margin-left:50px; + height:100%; + transition-duration: 0.5s; + background-color: #fcbb00; + border: 2px solid #fcbb00; + border-radius: 45px; +} + +.bouton2:hover{ + background-color: #06395a; + border: 2px solid #06395a; + cursor:pointer; +} + +#bouton2{ + color:white; + font-size: 100%; + font-family:Arial Black; +} +#boutonProd{ + align-self: flex-end; + height: 15%; +} diff --git a/Fichiers src site-web/include/logo.png b/Fichiers src site-web/include/logo.png new file mode 100644 index 00000000..a73f3aa8 Binary files /dev/null and b/Fichiers src site-web/include/logo.png differ diff --git a/Fichiers src site-web/include/produit.css b/Fichiers src site-web/include/produit.css new file mode 100644 index 00000000..74db85ee --- /dev/null +++ b/Fichiers src site-web/include/produit.css @@ -0,0 +1,202 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&display=swap'); + +html{ +background-color : #1AE2F9; +font-family:Poppins; +} + +input[type="text"]{ + + border: 1px solid #111; + border-radius: 20px; + width: 130px; + height: 25px; + padding-left: 30px; + outline: none; + +} + +input[type="submit"]{ + + color : white; + font-family: Arial Black; + width: 120px; + height: 35px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +input[type="submit"]:hover{ + + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; + +} + +a{ + +text-decoration:none; +color : white; +font-family : Arial Black; +} + +.aucunresultat{ + +margin-top:20px; +padding-bottom : 60%; +font-weight: 500; +font-size:40px; +margin-left:120%; +width:100%; + +} + +.input { + + display:flex; + flex-direction: column; + margin-top:10%; + justify-content : flex-start; + gap:20px; +} + +.input2{ + align-items: center; + display: flex; + justify-content: center; + gap: 20px; +} + +.input3{ + align-items: center; + display: flex; + justify-content: center; + gap: 20px; +} + + + +.loupe i { + position: absolute; + margin-left:10px; + margin-top:8px; +} + + +button{ + color : white; + font-family: Arial Black; + width: 120px; + height: 35px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +#infos{ +color : white; + font-family: Arial Black; + width:130px; + height : 40px; + transition-duration: 0.5s; + background-color: #06395a; + border: 2px solid #06395a; + border-radius: 45px; + +} + +#infos:hover{ +background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; + +} + +button:hover{ + background-color: #fcbb00; + border: 2px solid #fcbb00; + cursor:pointer; +} + + +.recherche{ + font-size : 15px; +} + +.produits{ + padding: 0 6%; +} +.produit_header{ + margin-top: 50px; + display: flex; + justify-content: space-between; + align-items: center; +} +.produit_header .title{ + font-size: 30px; + font-weight: 500; +} + +.produit_container{ + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 50px; + margin-top: 60px; +} + +.card{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-bottom: 20px; + border-radius: 10px; + border : 2px solid #06395a; + background-color : #06f9f1; + +} + +.card .image img{ + width: 400px; + height: 400px; + object-fit: contain; + +} + +.card .title{ + font-size: 20px; + font-weight: 500; + margin-bottom: 10px; + margin-top: -30px; +} + +.card .categorie{ + font-size: 20px; + font-weight: 500; + margin-bottom: 10px; +} + + +.card .prix{ + color: #111; + font-size: 20px; + margin-bottom: 30px; +} + + +.card .boutons{ + display: flex; + gap: 30px; +} + +.card:hover{ + cursor : pointer; + +} + diff --git a/Fichiers src site-web/index.php b/Fichiers src site-web/index.php new file mode 100644 index 00000000..83e1a7e0 --- /dev/null +++ b/Fichiers src site-web/index.php @@ -0,0 +1,43 @@ + + + + + + SubOne Accueil + + + + + + + + + + + Bonjour, '. $_SESSION['prenom']. ' ! '; + } + + ?> + + +
+ +
+ +
+ + + +
+ + + + diff --git a/Fichiers src site-web/piege.js b/Fichiers src site-web/piege.js new file mode 100644 index 00000000..75b32e7d --- /dev/null +++ b/Fichiers src site-web/piege.js @@ -0,0 +1,45 @@ +var allowedKeys = { + 65: 'a', + 68: 'd', + 77: 'm', + 73: 'i', + 78: 'n' + }; + + var konamiCode = ['a', 'd', 'm', 'i', 'n']; + + var konamiCodePosition = 0; + + document.addEventListener('keydown', function(e) { + + var key = allowedKeys[e.keyCode]; + var requiredKey = konamiCode[konamiCodePosition]; + if (key == requiredKey) { + konamiCodePosition++; + + if (konamiCodePosition == konamiCode.length) { + activateCheats(); + konamiCodePosition = 0; + } + } else { + konamiCodePosition = 0; + } + }); + + function activateCheats() { + alert("Vous allez accéder à la partie administrateur du site."); + document.location.href = "GestionProduit.php"; + + + } + + + //, 't', 'g', 'a', 'y' + + /*76: 'l', + 69: 'e', + 86: 'v', + 83: 's', + 84: 't', + 71: 'g', + 89: 'y'*/ \ No newline at end of file diff --git a/Fichiers src site-web/script.js b/Fichiers src site-web/script.js new file mode 100644 index 00000000..12340929 --- /dev/null +++ b/Fichiers src site-web/script.js @@ -0,0 +1,40 @@ +var allowedKeys = { + 76: 'l', + 69: 'e', + 86: 'v', + 83: 's', + 84: 't', + 71: 'g', + 65: 'a', + 89: 'y' + }; + + var konamiCode = ['l', 'e', 'v', 'e', 's', 't', 'g', 'a', 'y']; + + var konamiCodePosition = 0; + + document.addEventListener('keydown', function(e) { + + var key = allowedKeys[e.keyCode]; + var requiredKey = konamiCode[konamiCodePosition]; + if (key == requiredKey) { + konamiCodePosition++; + + if (konamiCodePosition == konamiCode.length) { + activateCheats(); + konamiCodePosition = 0; + } + } else { + konamiCodePosition = 0; + } + }); + + function activateCheats() { + alert("Toi aussi tu trouves que le V est gay ?!"); + document.location.href = "GestionProduit.php"; + + + var audio = new Audio('images/leV.mp3'); + audio.play(); + + } \ No newline at end of file diff --git a/Fichiers src site-web/supprArticle.php b/Fichiers src site-web/supprArticle.php new file mode 100644 index 00000000..f6e18e34 --- /dev/null +++ b/Fichiers src site-web/supprArticle.php @@ -0,0 +1,87 @@ + diff --git a/Fichiers src site-web/traitPanier.php b/Fichiers src site-web/traitPanier.php new file mode 100644 index 00000000..c34e2740 --- /dev/null +++ b/Fichiers src site-web/traitPanier.php @@ -0,0 +1,161 @@ + + alert(" Diantre, arr�tez de modifier cet URl !"); + location.href = "index.php"; + '; + exit(); + + } + +//variables + + $nbarticle = $_POST['nbarticle']; + + $idclient = $_SESSION['idclient']; + + $idarticle = htmlentities($_GET['idarticle']); + + $qteenstock = htmlentities($_GET['qtestock']); + + $prixunitaire = htmlentities($_GET['prix']); + + + if($nbarticle > $qteenstock){ + echo ''; + exit(); + + } + + $idpanier = "SELECT idPanier FROM PANIER WHERE idClient = :pID_CLIENT"; + + $panier2 = oci_parse($connect, $idpanier); + + oci_bind_by_name($panier2, ":pID_CLIENT", $idclient); + + // ex�cution de la requ�te + oci_execute($panier2); + +// si le client n'a pas de panier, on lui en cr�� un + if (($panier3 = oci_fetch_assoc($panier2)) == false){ + + $createpanier = "INSERT INTO PANIER VALUES (:pID_PANIER, :pID_CLIENT, 0)"; + + // pr�paration de la requ�te + $createpanier2 = oci_parse($connect, $createpanier); + + oci_bind_by_name($createpanier2, ":pID_PANIER", $idclient); + + oci_bind_by_name($createpanier2, ":pID_CLIENT", $idclient); + + // ex�cution de la requ�te + oci_execute($createpanier2); + + //commit + oci_commit($connect); + + } + + // requ�te v�rifiant si l'article ajout� est d�j� dans le panier + $reqdejapanier = "SELECT * FROM DETAILPANIER WHERE idPanier = :pID_PANIER AND idArticle = :pID_ARTICLE"; + + $dejapanier = oci_parse($connect, $reqdejapanier); + + oci_bind_by_name($dejapanier, ":pID_PANIER", $idclient); + + oci_bind_by_name($dejapanier, ":pID_ARTICLE", $idarticle); + + // ex�cution de la requ�te + oci_execute($dejapanier); + + // si l'article ajout� est d�j� dans le panier, on modifie sa quantit� + if (($test = oci_fetch_assoc($dejapanier)) != false){ + + if (($test['NBARTICLE'] + $nbarticle) > $qteenstock) { + echo ''; + exit(); + } + //modification de la quantit� + $reqmodifpanier = "UPDATE DETAILPANIER SET NBARTICLE = NBARTICLE + :pNB_ARTICLE WHERE idPanier = :pID_PANIER AND idArticle = :pID_ARTICLE"; + + + // pr�paration de la requ�te + $modifpanier = oci_parse($connect, $reqmodifpanier); + + + oci_bind_by_name($modifpanier, ":pNB_ARTICLE", $nbarticle); + + oci_bind_by_name($modifpanier, ":pID_ARTICLE", $idarticle); + + oci_bind_by_name($modifpanier, ":pID_PANIER", $idclient); + + // ex�cution de la requ�te + oci_execute($modifpanier); + + //commit + oci_commit($connect); + + //redirection vers le panier + + header("location: Panier.php?idclient=$idclient"); + exit(); + + } + + else { + + // sinon on ajoute l'article au panier + + $article = oci_fetch_assoc($panier2); + + $idPanier = $article['IDPANIER']; + + //on ajoute l'article d�sir� au panier du client + $req = "INSERT INTO DETAILPANIER VALUES (:pID_PANIER, :pID_ARTICLE, :pNB_ARTICLE, :pPRIX_QTE_ARTICLE)"; + + // pr�paration de la requ�te + $panier = oci_parse($connect, $req); + + oci_bind_by_name($panier, ":pID_PANIER", $idclient); + + oci_bind_by_name($panier, ":pID_ARTICLE", $idarticle); + + oci_bind_by_name($panier, ":pNB_ARTICLE", $nbarticle); + + oci_bind_by_name($panier, ":pPRIX_QTE_ARTICLE", $prixunitaire); + + // ex�cution de la requ�te + oci_execute($panier); + + //commit + oci_commit($connect); + + //lib�ration de la m�moire + oci_free_statement($panier); + + //redirection vers le panier + + header("location: Panier.php?idclient=$idclient"); + exit(); + +} + +?> + + diff --git a/Fichiers src site-web/traitSupprPanier.php b/Fichiers src site-web/traitSupprPanier.php new file mode 100644 index 00000000..2f894c86 --- /dev/null +++ b/Fichiers src site-web/traitSupprPanier.php @@ -0,0 +1,37 @@ + + + \ No newline at end of file diff --git a/README.adoc b/README.adoc index 103838db..c12fdfca 100644 --- a/README.adoc +++ b/README.adoc @@ -49,13 +49,14 @@ toc::[] == Equipe -Projet est réalisé par:: +Le projet est réalisé par:: -- https://github.com/janeDoe[Jane Doe] -- https://github.com/johnSmith[John Smith] -... +- https://github.com/EnzoMancini[Enzo Mancini] +- https://github.com/EstebanBiret[Esteban Biret-Toscano] +- https://github.com/haisondang[Hai Son Dang] +- https://github.com/Marwwannn[Marwan Youmni] -Tuteur/tutrice enseignant(e) de l'équipe:: mailto:jean-michel.bruel@univ-tlse2.fr[JMB] +Tuteur/tutrice enseignant(e) de l'équipe:: mailto:laurence.redon@univ-tlse2.fr[LR] == Contexte général @@ -90,6 +91,23 @@ TIP: Pensez à utiliser les salons Discord dédiés pour poser vos questions. TIP: Mettez ici toutes les informations nécessaire à l'utilisation de votre dépôt (comment on installe votre application, où sont les docs, etc.) +|=========================================================== +|Nom du dossier|Lien +| Partie BD (rendus de Webetud dupliqués ici)| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/Base%20de%20donn%C3%A9es[ici] +| Partie Web (rendus de Webetud dupliqués ici)| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/D%C3%A9veloppement%20Web[ici] +| Partie Communication (rendus de Webetud dupliqués ici)| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/Communication[ici] +| Fichiers src du Site-Web| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/Fichiers%20src%20site-web[ici] +| Fichiers src IOT| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/Fichiers%20src%20IOT[ici] +| Documentation technique WEB à jour| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Documentation%20technique%20WEB%20V6.pdf[ici] +| Documentation utilisateur WEB finalisée |https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Documentation%20utilisateur%20WEB%20finalis%C3%A9e%20(V6.1).pdf[ici] +| Documentation Python|https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/Documentation%20Python[ici] +| Tests WEB à jour| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Tests/Test%20Web%20V6.0.adoc[ici] +| Tests Python| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Tests/Test%20Python.py[ici] +| Tests BD V5.0| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Tests/Test%20BD.pdf[ici] +| Analyse d'impact| https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Droit%20analyse%20impact.pdf[ici] +| Documentation technique JAVA | https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation%20Java/G1B-6%20Documentation%20technique%20Java.pdf[ici] +|=========================================================== + == Gestion de projet & Qualité Chaque sprint (semaine) vous devrez livrer une nouvelle version de votre application (release). @@ -97,10 +115,35 @@ Utilisez pour cela les fonctionnalités de GitHub pour les https://docs.github.c De plus ce fichier `README.adoc` devra être à jour des informations suivantes : -- Version courante : https://github.com/IUT-Blagnac/sae3-01-template/releases/tag/v0.1.2[v0.1.2] -- Lien vers la doc technique -- Lien vers la doc utilisateur -- Liste des (ou lien vers les) User Stories (ToDo/Ongoing/Done) et % restant -- Tests unitaires et plans de test +- Version courante : https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/releases/tag/V6.1[V6.1] +- https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Backlog%20Produit%20IOT%20%26%20E-commerce.adoc[Backlog produit IOT & E-commerce] +- https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Backlog%20Produit%20Sprint%207.adoc[Backlog de Sprint 7] +- https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Documentation%20technique%20WEB%20V6.pdf[Documentation technique Web à jour] +- https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/blob/master/Documentation/Documentation%20utilisateur%20WEB%20finalis%C3%A9e%20(V6.1).pdf[Documentation utilisateur Web finalisée] +- https://github.com/orgs/IUT-Blagnac/projects/33[Projet Site Web] +- https://github.com/orgs/IUT-Blagnac/projects/40[Projet IOT] +- https://github.com/IUT-Blagnac/sae3-01-devapp-g1b-6/tree/master/Tests[Tests WEB / IOT / BD] - Indicateurs de qualité du code (dette technique) -- ... tout autre élément que vous jugerez utiles pour démontrer la qualité de votre application \ No newline at end of file +- ... tout autre élément que vous jugerez utiles pour démontrer la qualité de votre application + +=== Évaluations hebdomadaires + +NOTE: Les notes ci-dessous sont mises à jour directement par les enseignants responsables de la compétence 5. + +ifdef::env-github[] +image:https://docs.google.com/spreadsheets/d/e/2PACX-1vTc3HJJ9iSI4aa2I9a567wX1AUEmgGrQsPl7tHGSAJ_Z-lzWXwYhlhcVIhh5vCJxoxHXYKjSLetP6NS/pubchart?oid=1950296416&format=image[link=https://docs.google.com/spreadsheets/d/e/2PACX-1vTc3HJJ9iSI4aa2I9a567wX1AUEmgGrQsPl7tHGSAJ_Z-lzWXwYhlhcVIhh5vCJxoxHXYKjSLetP6NS/pubchart?oid=1950296416&format=image] +endif::[] + +ifndef::env-github[] +++++ + +++++ +endif::[] + +=Sprint 3 retour : +Backlog Ecommerce ok même si des erreurs de syntaxe dans la rédaction. Par contre pourquoi j'ai une colonne US puis Backlog produit ? J'ai encore des "en cours" dans un sprint qui est terminé. Les tâches doivent avoir un label et être assignées. Elles sont aussi ratachées à une US. En IOT pas de backlog produit ni d'organisation en sprint, juste une liste d'issues sans label ni assignement. Des livraisons mais des tests que sur l'IOT. Je n'ai pas touvé vos docs tech et user. + + + + +https://docs.google.com/spreadsheets/d/e/2PACX-1vTc3HJJ9iSI4aa2I9a567wX1AUEmgGrQsPl7tHGSAJ_Z-lzWXwYhlhcVIhh5vCJxoxHXYKjSLetP6NS/pubchart?oid=1950296416&format=interactive diff --git a/Tests/Test BD.pdf b/Tests/Test BD.pdf new file mode 100644 index 00000000..4a93829d Binary files /dev/null and b/Tests/Test BD.pdf differ diff --git a/Tests/Test Python.py b/Tests/Test Python.py new file mode 100644 index 00000000..e9cc31f2 --- /dev/null +++ b/Tests/Test Python.py @@ -0,0 +1,38 @@ +import paho.mqtt.client as mqtt, json, base64 + +# The callback for when the client receives a CONNACK response from the server. +def on_connect(client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + + # Subscribing in on_connect() means that if we lose the connection and + # reconnect then subscriptions will be renewed. + client.subscribe("application/1/device/+/event/up") + +# The callback for when a PUBLISH message is received from the server. +def on_message(client, userdata, msg): + Jmsg=json.loads(msg.payload) + mydata=Jmsg["object"] + if (mydata!=""): + print(mydata) + Jmydata=json.loads(mydata) + +#def bleu(): + # msg="blue" + # msg_bytes=msg.encode('ascii') + # b64_bytes=base64.b64encode(msg_bytes) + #b64_msg=b64_bytes.decode('ascii') + #print(b64_msg) + #payloadJson={"confirmed":False,"fPort":5,"data":b64_msg} + #client.publish(topic="application/1/device/0c7e450102030102/command/down",payload=json.dumps(payloadJson)) + +client = mqtt.Client() +client.on_connect = on_connect +client.on_message = on_message + +client.connect("chirpstack.iut-blagnac.fr", 1883, 60) + +# Blocking call that processes network traffic, dispatches callbacks and +# handles reconnecting. +# Other loop*() functions are available that give a threaded interface and a +# manual interface. +client.loop_forever() diff --git a/Tests/Test Web V6.0.adoc b/Tests/Test Web V6.0.adoc new file mode 100644 index 00000000..cc9b4293 --- /dev/null +++ b/Tests/Test Web V6.0.adoc @@ -0,0 +1,141 @@ += Tests du site web V6.0, réalisés par Esteban BIRET-TOSCANO. +:toc: +:toc-title: Sommaire +:numbered: + +== Connexion + +L'utilisateur entre son adresse-mail et son mot de passe dans le formulaire de connexion (accessible en cliquant sur le bouton 'Connexion' du header). + +|======= +|Test |Attendu |Résultat +|Connexion avec compte client |Redirection vers accueil avec modification du header |Ok +|Connexion avec mdp incorrect|Redirection vers formulaire de connexion avec message d'erreur explicite |Ok +|Connexion avec compte inexistant |Redirection vers formulaire de connexion avec message d'erreur explicite|Ok +|Connexion en cliquant sur 'Se souvenir de moi' |Lors de la déconnexion puis connexion, le champ login est déjà pré-rempli|Ok +|======= + +== Déconnexion + +L'utilisateur appuie sur le bouton 'Déconnexion' du header. + +|======= +|Test |Attendu |Résultat +|Déconnexion du site |Redirection vers accueil avec modification du header | Ok +|======= + +== Inscription + +L'utilisateur entre différentes informations via un formulaire de création de compte (nom, prénom, adresse-mail, numéro de tel, mdp). +Les données entrées sont vérifiées par des REGEX pour valider ou non la création d'un compte. + +|======= +|Test |Attendu |Résultat +|Création compte client correct |Redirection vers accueil| Ok +|Création compte incorrect (un des champs n'est pas conforme)|Redirection vers formulaire avec message d'erreur explicite| Ok +|======= + +== Modification de compte + +Une fois connecté, l'utilisateur voit les informations de son compte (nom, prénom, numéro de tel, email). +Il peut cliquer sur le bouton 'Modifier' pour modifier les informations de son compte (même le mdp). + +|======= +|Test |Attendu |Résultat +|Cliquer sur le bouton 'Compte client' sans être connecté|Redirection vers formulaire de connexion| Ok +|Cliquer sur le bouton 'Compte client' |Redirection vers la page 'modifClient.php'| Ok +|Modifier ses informations | Lors de la soumission du formulaire avec les nouvelles informations, redirection vers l'accueil.| Ok +|Modifier ses informations incorrect (un des champs n'est pas conforme)|Redirection vers formulaire modifClient.php avec message d'erreur explicite| Ok +|Information bien mises à jour | Après avoir modifié son compte, les infos de celui-ci sont bien actualisées sur la page 'Compte Client'| Ok +|======= + +== Recherche d'articles par leurs noms + +L'utilisateur entre le nom d'un produit dans la barre de recherche de la page 'Produit.php' et appuie sur la touche 'Entrée' du clavier. + +|======= +|Test |Attendu |Résultat +|Saisie du nom d'un article présent |Affichage page de résultat avec liste des produits correspondants| Ok +|Saisie d'une chaine de caractères |Affichage page de résultat avec liste des produits comportant la chaine en question dans leurs noms (peut importe la casse !) | Ok +|Saisie du nom d'un article non présent |Affichage page de résultat vide | Ok +|Aucune saisie de nom |Affichage tous les produits| Ok +|======= + +== Recherche d'articles par leurs catégories + +L'utilisateur entre la catégorie d'un produit dans la barre de recherche de la page 'Produit.php' et appuie sur la touche 'Entrée' du clavier. +Il peut également cliquer sur les boutons représentant les 6 catégories de sous-marins. + +|======= +|Test |Attendu |Résultat +|Saisie d'une catégorie existante |Affichage page de résultat avec liste des produits appartenants à la catégorie en question| Ok +|Cliquer sur la catégorie 'Plaisance' |Affichage page de résultat avec liste des produits appartenants à la catégorie 'Plaisance'| Ok +|======= + +== Consulter le détail d'un produit + +L'utilisateur peut accéder aux informations d'un produit en cliquant dessus ou sur le bouton 'Informations'. + +|======= +|Test |Attendu |Résultat +|Cliquer sur un produit|Ouverture de la page du produit 'detailArticle.php'|Ok +|Cliquer sur le bouton prévu à cet effet|Ouverture de la page du produit 'detailArticle.php'|Ok +|======= + +== Panier + +L'utilisateur peut ajouter des articles à son panier, les supprimer, valider son panier ou supprimer l'intégralité du panier. + +|======= +|Test |Attendu |Résultat +| Ajouter un article au panier| Si l'utilisateur n'a pas de panier, un panier est créé, comportant l'article choisi par l'utilisateur. Il est redirigé vers la page panier.php| Ok +| Ajouter un même article en plusieurs exemplaires| L'utilisateur choisit sa quantité grâce à un input, avant de l'ajouter au panier. La quantité de l'article est affiché dans le panier| Ok +| Supprimer un article du panier| L'utilisateur clique sur le bouton 'Supprimer' présent sur chaque article du panier. L'article est supprimé du panier au niveau BD, et il n'est plus affiché sur le panier coté WEB| Ok +| Supprimer le panier| Si l'utilisateur Clique sur 'Supprimer le panier', le contenu du panier est supprimé coté BD, et coté WEB, un message indique à l'utilisateur que son panier est vide, et lui invite à consulter la page produit, à l'aide d'un bouton. | Ok +| Prix du panier| Le prix du panier varie en fonction des articles & de leurs quantités, il est affiché en haut à droite du panier et change également coté BD à chaque modification du panier (ajout/retrait d'articles)| Ok +| Le panier du client est permanent, jusqu'à ce qu'il le modifie / valide / supprime | Une fois déconnecté, je peux me reconnecter un certain temps plus tard, et voir que mon panier reste inchangé| Ok +| Valider le panier| L'utilisateur clique sur le bouton 'Valider le panier', il est ensuite redirigé vers la page qui s'occupe de prendre les informations de paiement, présentant un bouton 'Retour au panier' et un bouton 'Valider la commande'| Pas encore développé +|======= + +== Supprimer un compte + +L'utilisateur peut supprimer son compte en cliquant sur le bouton 'Compte client' dans le header, puis en cliquant sur 'Supprimer' + +|======= +|Test |Attendu |Résultat +| L'utilisateur clique sur 'Supprimer'| Un pop-up de confirmation en Javascript apparait, demandant si l'utilisateur veut réellement supprimer son compte| Ok +|L'utilisateur clique sur 'Annuler' | L'utilisateur reste sur la page 'Compte client', rien n'a été changé|Ok +|L'utilisateur clique sur 'Ok' | Un pop-up d'alerte indique à l'utilisateur que son compte a bien été supprimé, il est ensuite redirigé vers l'accueil, en étant bien sûr déconnecté. Coté BD, l'utilisateur a été supprimé de la table 'Client', ainsi que son panier et son contenu|Ok +|L'utilisateur essaye de se connecter avec son ancien compte | Après avoir validé le formulaire de connexion, un pop-up d'alerte indique à l'utilisateur que ce compte n'existe pas|Ok +|======= + +== Commande + +En ayant au moins un article dans son panier, l'utilisateur peut la valider et passer à la commande. Il peut également visualiser ses anciennes commandes. + +|======= +|Test |Attendu |Résultat +| L'utilisateur clique sur 'Valider' dans la page panier| Il est redirigé vers une page présentant un formulaire pour le paiement|Ok +| Une fois sur cette page, l'utilisateur décide de revenir à son panier en cliquant sur le bouton 'Retour au panier'| L'utilisateur est ramené vers son panier, qui reste inchangé|Ok +| L'utilisateur clique sur 'Valider' dans la page commande, alors que toutes les informations ne sont pas remplies| L'utilisateur reste sur cette page, et le formulaire indique le/les champs vide.s|Ok +| L'utilisateur clique sur 'Valider' dans la page commande, en ayant mal rempli un ou plusieurs champs (REGEX non respectée.s)| L'utilisateur reste sur cette page, et le formulaire indique le/les champs incorrects via un pop-up JS|Ok +| L'utilisateur clique sur 'Valider' dans la page commande, en ayant rempli toutes ses informations correctement| Un pop-up l'informe que sa commande a bien été validée, et l'utilisateur est redirigé vers la page d'accueil. Côté BD, une ligne est ajoutée dans la table 'Commande', et plusieurs dans la table 'detailCommande', en fonction du nombre d'articles différents commandés.|Ok +| L'utilisateur revient sur son panier une fois la commande passée| Le panier affiche 'Votre panier est vide !'. Côté BD, le panier du client et son contenu sont supprimés après la commande|Ok +| L'utilisateur clique sur le bouton 'Mes commandes', sur la page du compte client|Une page affiche toutes les commandes du client, avec pour chacune la possibilité de voit son détail à l'aide d'un bouton|Ok +| L'utilisateur clique sur le détail d'une de ses commandes|La page detailCommande.php affiche tous les articles de la commande en question, avec pour chacun le prix unitaire et la quantité commandée. Un bouton tout en bas de la page permet de revenir à ses commandes |Ok +|======= + +== Espace administrateur + +Fonctionnalité ajouter/retirer du stock sur chaque article. + +|======= +|Test |Attendu |Résultat +| L'utilisateur tape 'admin' suivi de la touche 'Entrée' sur la page d'accueil du site|Un pop-up JS apparait, indiquant à la personne qu'elle va accéder à l'espace administrateur. Il ensuite redirigé vers la page de gestion des articles |Ok +| Sur la page GestionProduit.php, l'utilisateur clique sur le bouton 'Ajouter du stock'|Il accède à un formulaire où il doit choisir l'article et la quantité à ajouter |Ok +| Après avoir rempli le formulaire, il clique sur le bouton 'Valider'|Un pop-up JS apparait, indiquant à la personne combien d'articles ont été ajoutés, puis redirection sur la page GestionProduit.php |Ok +| Sur la page GestionProduit.php, l'utilisateur clique sur le bouton 'Retirer du stock'|Il accède à un formulaire où il doit choisir l'article et la quantité à retirer |Ok +| Après avoir rempli le formulaire, il clique sur le bouton 'Valider'|Un pop-up JS apparait, indiquant à la personne combien d'articles ont été retirés, puis redirection sur la page GestionProduit.php |Ok +| Après avoir rempli le formulaire, il clique sur le bouton 'Valider', alors qu'il a retiré plus de stock que l'article en a actuellement|Un pop-up JS apparait, indiquant à la personne combien d'articles n'ont pas pu être ajoutés et le stock actuel de l'article en question, puis on reste sur la page. Aucun stock n'a été modifié |Ok +| Sur ces 2 pages, un bouton 'Retour à la gestion' est présent, permettant de revenir à cette page à tout moment|L'utilisateur clique sur ce bouton, il est redirigé vers la page GestionProduit.php|Ok +|=======