From 934f646efa0824489bf38decd01d02f5702dd5a8 Mon Sep 17 00:00:00 2001
From: marcantoinem <marc-antoine.m@outlook.com>
Date: Sat, 27 Jul 2024 13:54:05 -0400
Subject: [PATCH] Improve number input

---
 aep-schedule-website/src/backend/state.rs     | 24 +++++---
 .../components/common/number_input.rs         | 61 ++++++++++++++++---
 .../src/frontend/components/options/form.rs   |  2 +-
 .../components/options/optimizations.rs       |  6 +-
 4 files changed, 70 insertions(+), 23 deletions(-)

diff --git a/aep-schedule-website/src/backend/state.rs b/aep-schedule-website/src/backend/state.rs
index a9b37e0..391be8e 100644
--- a/aep-schedule-website/src/backend/state.rs
+++ b/aep-schedule-website/src/backend/state.rs
@@ -36,16 +36,20 @@ pub struct AppState {
 
 impl AppState {
     pub async fn new(leptos_options: LeptosOptions, routes: Vec<RouteListing>) -> Self {
-        let client = reqwest::Client::builder()
-            .user_agent("NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)")
-            .build()
-            .unwrap();
-        let horsage = client.get(HORSAGE_URL).send().await.unwrap();
-        let horsage = horsage.text().await.unwrap();
-        let fermes = client.get(FERME_URL).send().await.unwrap();
-        let fermes = fermes.text().await.unwrap();
-        fs::write("horsage.csv", horsage).expect("Unable to write file");
-        fs::write("fermes.csv", fermes).expect("Unable to write file");
+        #[cfg(not(debug_assertions))]
+        {
+            // Don't spam Poly when reloading the website in debug mode
+            let client = reqwest::Client::builder()
+                .user_agent("NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)")
+                .build()
+                .unwrap();
+            let horsage = client.get(HORSAGE_URL).send().await.unwrap();
+            let horsage = horsage.text().await.unwrap();
+            let fermes = client.get(FERME_URL).send().await.unwrap();
+            let fermes = fermes.text().await.unwrap();
+            fs::write("horsage.csv", horsage).expect("Unable to write file");
+            fs::write("fermes.csv", fermes).expect("Unable to write file");
+        }
         let horsage = BufReader::new(File::open("horsage.csv").unwrap());
         let fermes = BufReader::new(File::open("fermes.csv").unwrap());
         let courses = Arc::new(RwLock::new(Courses::from_csv(horsage, fermes)));
diff --git a/aep-schedule-website/src/frontend/components/common/number_input.rs b/aep-schedule-website/src/frontend/components/common/number_input.rs
index ad2ba1d..718ad19 100644
--- a/aep-schedule-website/src/frontend/components/common/number_input.rs
+++ b/aep-schedule-website/src/frontend/components/common/number_input.rs
@@ -1,19 +1,62 @@
 use leptos::*;
 
 #[component]
-pub fn NumberInput(#[prop(optional, into)] value: RwSignal<u8>, max: u8) -> impl IntoView {
+pub fn NumberInput<F>(
+    #[prop(optional, into)] value: RwSignal<u8>,
+    max: u8,
+    label: &'static str,
+    submit: F,
+) -> impl IntoView
+where
+    F: Fn() + Copy + 'static,
+{
     let on_input = move |ev| {
         value.set(event_target_value(&ev).parse::<u8>().unwrap());
+        submit();
+    };
+
+    let minus = move |_| {
+        let v = value.get();
+        if v > 0 {
+            value.set(v - 1);
+            submit();
+        }
+    };
+
+    let plus = move |_| {
+        let v = value.get();
+        if v != u8::MAX {
+            value.set(v + 1);
+            submit();
+        }
+        submit();
     };
 
     view! {
-        <input
-            on:input=on_input
-            type="number"
-            min="0"
-            max=max
-            prop:value=value
-            class="number-input"
-        />
+        <div class="flex flex-row gap-8 items-center">
+            <p class="text-white font-sans">{label}</p>
+            <div class="relative flex items-center max-w-20">
+                <button on:click=minus type="button" class="bg-gray-100 hover:bg-gray-200 border border-gray-300 rounded-s-lg p-1 h-7 focus:ring-gray-100 focus:ring-2 focus:outline-none">
+                    <svg class="w-3 h-3 text-gray-900" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 2">
+                        <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h16"/>
+                    </svg>
+                </button>
+                <input
+                    type="numeric"
+                    class="bg-gray-50 border-x-0 border-gray-300 h-7 text-center text-gray-900 text-sm focus:ring-amber-500 focus:border-amber-500 block w-full py-2.5"
+                    placeholder="0"
+                    on:input=on_input
+                    type="number"
+                    min="0"
+                    max=max
+                    prop:value=value
+                    required />
+                <button on:click=plus type="button" class="bg-gray-100 hover:bg-gray-200 border border-gray-300 rounded-e-lg p-1 h-7 focus:ring-gray-100 focus:ring-2 focus:outline-none">
+                    <svg class="w-3 h-3 text-gray-900" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18">
+                        <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 1v16M1 9h16"/>
+                    </svg>
+                </button>
+            </div>
+        </div>
     }
 }
diff --git a/aep-schedule-website/src/frontend/components/options/form.rs b/aep-schedule-website/src/frontend/components/options/form.rs
index 01cf4fc..7b63932 100644
--- a/aep-schedule-website/src/frontend/components/options/form.rs
+++ b/aep-schedule-website/src/frontend/components/options/form.rs
@@ -28,7 +28,7 @@ pub fn OptionsForms(action: Action<SchedulesOptions, Vec<Schedule>>) -> impl Int
     view! {
         <CoursesSelector state=state submit/>
         <span class="grow"></span>
-        <div class="row-container input-item auto-bottom"><p>"Nombre de conflits maximum"</p><NumberInput value=state.max_nb_conflicts max=127/></div>
+        <NumberInput value=state.max_nb_conflicts max=127 label="Nombre de période de cours en conflits maximum: " submit/>
         <SelectOptimizations state=state submit/>
         <button on:click=submit_mobile class="lg:hidden select-none rounded-lg bg-amber-500 py-2 text-xl px-4 w-64 self-center text-center align-middle text-black shadow-md shadow-amber-500/20 transition-all hover:shadow-lg hover:shadow-amber-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none">"Générer les horaires"</button>
     }
diff --git a/aep-schedule-website/src/frontend/components/options/optimizations.rs b/aep-schedule-website/src/frontend/components/options/optimizations.rs
index 52d500f..e945853 100644
--- a/aep-schedule-website/src/frontend/components/options/optimizations.rs
+++ b/aep-schedule-website/src/frontend/components/options/optimizations.rs
@@ -30,7 +30,7 @@ where
             <div class="col-container">
                 <House weight=weight_house size="10vh"/>
                 <p>"Plus de congés"</p>
-                <input type="range" min="0" max="4" class="opti-slider" prop:value=state.day_off  on:input=move |ev| {
+                <input type="range" min="0" max="4" class="opti-slider accent-amber-500" prop:value=state.day_off  on:input=move |ev| {
                     state.day_off.set(event_target_value(&ev).parse::<u8>().unwrap());
                     submit();
                 }/>
@@ -41,7 +41,7 @@ where
                     <Sun weight=weight_morning size="10vh"/>
                 </div>
                 <p>"Cours plus tôt ou plus tard"</p>
-                <input type="range" min="-4" max="4" class="opti-slider" prop:value=state.morning  on:input=move |ev| {
+                <input type="range" min="-4" max="4" class="opti-slider accent-amber-500" prop:value=state.morning  on:input=move |ev| {
                     state.morning.set(event_target_value(&ev).parse::<i8>().unwrap());
                     submit();
                 }/>
@@ -49,7 +49,7 @@ where
             <div class="col-container">
                 <CalendarCheck weight=weight_finish size="10vh"/>
                 <p>"Finir plus tôt"</p>
-                <input type="range" min="0" max="4" class="opti-slider" prop:value=state.finish_early  on:input=move |ev| {
+                <input type="range" min="0" max="4" class="opti-slider accent-amber-500" prop:value=state.finish_early  on:input=move |ev| {
                     state.finish_early.set(event_target_value(&ev).parse::<u8>().unwrap());
                     submit();
                 }/>
-- 
GitLab