From c769e6c28fb7439081d33c26d82044f029d316db Mon Sep 17 00:00:00 2001
From: "thibault.capt" <thibault.capt@hes-so.ch>
Date: Wed, 25 Oct 2023 15:12:23 +0200
Subject: [PATCH] import / export from json

---
 Cargo.toml            |  5 ++++-
 src/app.rs            | 41 ++++++++++++++++++++++++++++++++++++++---
 src/training.rs       | 20 +++++++++++++++++++-
 training_session.json | 22 ++++++++++++++++++++++
 4 files changed, 83 insertions(+), 5 deletions(-)
 create mode 100644 training_session.json

diff --git a/Cargo.toml b/Cargo.toml
index 55a9725..edc4698 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,4 +6,7 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-cursive = "0.19.0"
\ No newline at end of file
+cursive = "0.19.0"
+serde = {version = "1.0.0", features = ["derive"]}
+serde_json = "1.0"
+
diff --git a/src/app.rs b/src/app.rs
index 71b86e9..c8a2872 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -25,14 +25,27 @@ pub fn run() {
         .child(Button::new("Add new", add_training)) // Bouton pour ajouter un nouvel entraînement
         .child(Button::new("Delete", delete_training)) // Bouton pour supprimer un entraînement
         .child(DummyView) // Vue fictive pour ajouter de l'espace
-        .child(Button::new("Quit", Cursive::quit)); // Bouton pour quitter l'application
+        .child(Button::new("Quit", application_close)); // Bouton pour quitter l'application
 
     // Ajout de la couche de dialogue principale à Cursive
     siv.add_layer(Dialog::around(LinearLayout::horizontal()
         .child(select) // Ajout de la vue de sélection
         .child(DummyView) // Ajout d'espace vide
         .child(buttons)) // Ajout des boutons
-        .title("Select a training")); // Titre de la couche de dialogue
+        .title("Training session")); // Titre de la couche de dialogue
+
+    // Rajouter les entraînements sauvegarder dans le json
+    let trainings = load_from_json("training_session.json");
+    match trainings {
+        Ok(training_list) => {
+            for training in training_list.iter() {
+                siv.call_on_name("select", |view: &mut SelectView<Training>| {
+                    view.add_item(training.name.clone(), training.clone());
+                });
+            }
+        }
+        Err(err) => eprintln!("Error loading from JSON: {}", err),
+    }
 
     // Exécution de la boucle principale de Cursive
     siv.run();
@@ -47,7 +60,7 @@ fn add_training(s: &mut Cursive) {
     fn ok(s: &mut Cursive, training: Training) {
         // Ajout de l'entraînement à la vue de sélection
         s.call_on_name("select", |view: &mut SelectView<Training>| {
-            view.add_item(training.name.clone(), training.clone()); // Using the cloned_training
+            view.add_item(training.name.clone(), training.clone());
         });
 
         s.pop_layer(); // Fermer la couche de dialogue
@@ -69,6 +82,7 @@ fn add_training(s: &mut Cursive) {
                         // Récupération des données saisies par l'utilisateur
                         let name = get_view_content(s, "name");
                         let description = get_view_content(s, "description");
+                        // TODO Vérifier format date
                         let date = get_view_content(s, "date");
                         let location = get_view_content(s, "location");
                         let duration = get_view_content(s, "duration").parse::<i32>().unwrap_or(0);
@@ -150,4 +164,25 @@ fn on_submit(s: &mut Cursive, training: &Training) {
                     })
                     .scrollable() // Permettre le défilement si le contenu dépasse
     );
+}
+
+fn application_close(s: &mut Cursive) {
+    let select = s.find_name::<SelectView<Training>>("select").unwrap();
+    let trainings = Training::extract_trainings_from_view(&select);
+    if let Err(err) = save_to_json(&trainings, "training_session.json") {
+        eprintln!("Error saving to JSON: {}", err);
+    }
+    s.quit();
+}
+
+fn save_to_json(trainings: &Vec<&Training>, file_path: &str) -> std::io::Result<()> {
+    let serialized = serde_json::to_string_pretty(trainings)?;
+    std::fs::write(file_path, serialized)?;
+    Ok(())
+}
+
+fn load_from_json(file_path: &str) -> std::io::Result<Vec<Training>> {
+    let contents = std::fs::read_to_string(file_path)?;
+    let data: Vec<Training> = serde_json::from_str(&contents)?;
+    Ok(data)
 }
\ No newline at end of file
diff --git a/src/training.rs b/src/training.rs
index 90631e0..a04a1eb 100644
--- a/src/training.rs
+++ b/src/training.rs
@@ -1,5 +1,10 @@
+extern crate serde;
+extern crate serde_json;
+
+use cursive::views::SelectView;
+
 /// Structure représentant un entraînement
-#[derive(Clone)]
+#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
 pub struct Training {
     /// Nom de l'entraînement
     pub name: String,
@@ -52,4 +57,17 @@ impl Training {
         format!("Name: {}\nDescription: {}\nDate: {}\nLocation: {}\nDuration: {}\nParticipants: {}",
                 self.name, self.description, self.date, self.location, self.duration.to_string(), self.participants.join(","))
     }
+
+    pub fn extract_trainings_from_view(select_view: &SelectView<Training>) -> Vec<&Training> {
+        let items = select_view.len();
+        let mut trainings = Vec::with_capacity(items);
+
+        for i in 0..items {
+            if let Some(training) = select_view.get_item(i) {
+                trainings.push(training.clone().1);
+            }
+        }
+
+        trainings
+    }
 }
\ No newline at end of file
diff --git a/training_session.json b/training_session.json
new file mode 100644
index 0000000..898ff8f
--- /dev/null
+++ b/training_session.json
@@ -0,0 +1,22 @@
+[
+  {
+    "name": "daiwdji",
+    "description": "jiijo",
+    "date": "ijo",
+    "location": "jio",
+    "duration": 0,
+    "participants": [
+      "jio"
+    ]
+  },
+  {
+    "name": "Foot",
+    "description": "fandn",
+    "date": "nn",
+    "location": "awd",
+    "duration": 0,
+    "participants": [
+      "nsda"
+    ]
+  }
+]
\ No newline at end of file
-- 
GitLab