diff --git a/aep-schedule-website/src/frontend/components/options/courses_selector.rs b/aep-schedule-website/src/frontend/components/options/courses_selector.rs
index 63ef9070b59f9728fcfaf8dd0b7e97555c85ec87..c0f062a24c7deb2836a10f63e32046eacc83cc8a 100644
--- a/aep-schedule-website/src/frontend/components/options/courses_selector.rs
+++ b/aep-schedule-website/src/frontend/components/options/courses_selector.rs
@@ -28,7 +28,7 @@ fn GroupsChips<F>(
 where
     F: Fn() + Copy + 'static,
 {
-    let set_modal = use_context::<SetModal>().unwrap().0;
+    let set_modal = SetModal::from_context();
 
     view! {
         <div on:click=move |_| {
diff --git a/aep-schedule-website/src/frontend/components/options/form.rs b/aep-schedule-website/src/frontend/components/options/form.rs
index d7d6efaf4959f7aaaee5618a666a37250bea8c9a..2f1206275af10658be4c10c26176599f58e22a56 100644
--- a/aep-schedule-website/src/frontend/components/options/form.rs
+++ b/aep-schedule-website/src/frontend/components/options/form.rs
@@ -12,20 +12,13 @@ use aep_schedule_generator::algorithm::{generation::SchedulesOptions, schedule::
 use leptos::*;
 
 #[component]
-pub fn OptionsForms<F>(
-    action: Action<SchedulesOptions, Vec<Schedule>>,
-    step: ReadSignal<u8>,
-    validate: F,
-) -> impl IntoView
-where
-    F: Fn(OptionState) + Copy + 'static,
-{
-    let state: OptionState = use_context().unwrap();
+pub fn OptionsForms(action: Action<SchedulesOptions, Vec<Schedule>>) -> impl IntoView {
+    let state = OptionState::from_context();
 
     let first_generation_done: FirstGenerationDone = use_context().unwrap();
     let submit = move || {
-        validate(state);
-        if !first_generation_done.0.get() || step.get() != 5 {
+        state.validate();
+        if !first_generation_done.0.get() || state.step.get() != 5 {
             return;
         }
         action.dispatch((&state).into());
diff --git a/aep-schedule-website/src/frontend/components/options/personal.rs b/aep-schedule-website/src/frontend/components/options/personal.rs
index 81cf017db580aa246b8df4198f675e5df0d7f132..bcfebc147a438d6c0d9d7049f089458aa0735ef1 100644
--- a/aep-schedule-website/src/frontend/components/options/personal.rs
+++ b/aep-schedule-website/src/frontend/components/options/personal.rs
@@ -59,7 +59,7 @@ where
         }
     };
     view! {
-        <Schedule col_height="0.35em">
+        <Schedule col_height="0.4em">
             {(0..5).into_iter().map(|i| {
                 (0..26).into_iter().map(|j| {
                     let j = 2 * j;
diff --git a/aep-schedule-website/src/frontend/components/options/state.rs b/aep-schedule-website/src/frontend/components/options/state.rs
index 8c9989b0eaa6f3224fad71946ffaa6052df54ece..2d974f4f7fd42fa53be60ca0ade4fb057b56f334 100644
--- a/aep-schedule-website/src/frontend/components/options/state.rs
+++ b/aep-schedule-website/src/frontend/components/options/state.rs
@@ -16,6 +16,51 @@ pub struct OptionState {
     pub day_off: RwSignal<u8>,
     pub morning: RwSignal<i8>,
     pub finish_early: RwSignal<u8>,
+    pub section_error: RwSignal<String>,
+    pub personal_error: RwSignal<String>,
+    pub step: RwSignal<u8>,
+}
+
+impl OptionState {
+    pub fn from_context() -> Self {
+        use_context().unwrap()
+    }
+
+    pub fn validate(self) {
+        let mut options: SchedulesOptions = (&self).into();
+        if options.courses_to_take.is_empty() {
+            self.step.set(1);
+            return;
+        }
+        let mut impossible_courses = options.get_impossible_course().into_iter();
+        if let Some(first_impossible_course) = impossible_courses.next() {
+            let mut error = format!("Les sections des/du cours {}", first_impossible_course);
+            for impossible_course in impossible_courses {
+                error.push_str(", ");
+                error.push_str(&impossible_course);
+            }
+            error.push_str(" sont toutes fermées.");
+            self.section_error.set(error);
+            self.step.set(2);
+            return;
+        }
+        self.section_error.set("".to_string());
+        options.apply_personal_schedule();
+        let mut impossible_courses = options.get_impossible_course().into_iter();
+        if let Some(first_impossible_course) = impossible_courses.next() {
+            let mut error = format!("Les sections des/du cours {}", first_impossible_course);
+            for impossible_course in impossible_courses {
+                error.push_str(", ");
+                error.push_str(&impossible_course);
+            }
+            error.push_str(" sont en conflits avec les heures libres sélectionnées.");
+            self.personal_error.set(error);
+            self.step.set(3);
+            return;
+        }
+        self.personal_error.set("".to_string());
+        self.step.set(5);
+    }
 }
 
 #[derive(Clone, Debug)]
@@ -77,6 +122,9 @@ impl Default for OptionState {
             day_off: create_rw_signal(3),
             morning: create_rw_signal(1),
             finish_early: create_rw_signal(1),
+            section_error: create_rw_signal("".to_string()),
+            personal_error: create_rw_signal("".to_string()),
+            step: create_rw_signal(0),
         }
     }
 }
diff --git a/aep-schedule-website/src/frontend/components/options/todo.rs b/aep-schedule-website/src/frontend/components/options/todo.rs
index 6ba9845852a8e2158739b7ec2263e8d6233213f6..b32e50fcfdbab84a7230e2628fcf196da0c12a9a 100644
--- a/aep-schedule-website/src/frontend/components/options/todo.rs
+++ b/aep-schedule-website/src/frontend/components/options/todo.rs
@@ -10,7 +10,7 @@ use crate::frontend::{
 #[component]
 pub fn Step(
     n: u8,
-    step: ReadSignal<u8>,
+    step: RwSignal<u8>,
     title: &'static str,
     description: &'static str,
     #[prop(optional)] children: Option<Children>,
@@ -48,13 +48,8 @@ pub fn Step(
 }
 
 #[component]
-pub fn Todo(
-    action: Action<SchedulesOptions, Vec<Schedule>>,
-    step: ReadSignal<u8>,
-    section_error: RwSignal<String>,
-    personal_error: RwSignal<String>,
-) -> impl IntoView {
-    let state: OptionState = use_context().unwrap();
+pub fn Todo(action: Action<SchedulesOptions, Vec<Schedule>>) -> impl IntoView {
+    let state = OptionState::from_context();
     let first_generation_done: FirstGenerationDone = use_context().unwrap();
 
     let submit = move |_| {
@@ -62,6 +57,8 @@ pub fn Todo(
         action.dispatch((&state).into())
     };
 
+    let step = state.step;
+
     let disab = move || {
         let step = step.get();
         match step {
@@ -76,10 +73,10 @@ pub fn Todo(
                 <div class="lg:py-6 lg:pr-16">
                     <Step n=1 step title="Ajoutez vos cours" description="Utilisez la barre de recherche à gauche pour trouver et sélectionner vos cours. Une fois les cours sélectionnés, ils apparaîtront comme un onglet."/>
                     <Step n=2 step title="Ouvrez des sections" description="Assurez d'avoir au moins une section d'ouverte pour la théorie et la pratique. En sélectionnant l'onglet du cours et en appuyant sur les sections.">
-                        <span class="text-red-800">{section_error}</span>
+                        <span class="text-red-800">{state.section_error}</span>
                     </Step>
                     <Step n=3 step title="Forcer des heures libres" description="Sélectionnez une plage de temps à avoir absolument libre en pressant et relâchant sur votre horaire personnel.">
-                        <span class="text-red-800">{personal_error}</span>
+                        <span class="text-red-800">{state.personal_error}</span>
                     </Step>
                     <Step n=4 step title="Ajustez les paramètres" description="Bougez les curseurs en bas pour ajuster vos préférences. Vous pouvez choisir d'avoir plus de congés, de commencer en moyenne les cours plus tôt ou plus tard, ou de finir en moyenne plus tôt."/>
                     <div class="flex items-center">
diff --git a/aep-schedule-website/src/frontend/components/schedules.rs b/aep-schedule-website/src/frontend/components/schedules.rs
index 0b2b70ad431fcc3da8c655f5d6d50cd1b2bde378..a1ec911a90e81cbbb0170677d78a48154a71f752 100644
--- a/aep-schedule-website/src/frontend/components/schedules.rs
+++ b/aep-schedule-website/src/frontend/components/schedules.rs
@@ -1,5 +1,6 @@
 use std::rc::Rc;
 
+use crate::frontend::components::options::state::OptionState;
 use crate::frontend::components::options::todo::Todo;
 use crate::{backend::routes::get_calendar, frontend::components::schedule::ScheduleComponent};
 use aep_schedule_generator::algorithm::generation::SchedulesOptions;
@@ -10,10 +11,8 @@ use leptos::*;
 pub fn SchedulesComponent(
     read_signal: RwSignal<Option<Vec<Schedule>>>,
     action: Action<SchedulesOptions, Vec<Schedule>>,
-    section_error: RwSignal<String>,
-    personal_error: RwSignal<String>,
-    step: ReadSignal<u8>,
 ) -> impl IntoView {
+    let step = OptionState::from_context().step;
     view! {
         <Await
             future=get_calendar
@@ -35,7 +34,7 @@ pub fn SchedulesComponent(
                         }
                    },
                     _ => view ! {
-                        <Todo action step section_error personal_error/>
+                        <Todo action/>
                     }
                 }
             }
diff --git a/aep-schedule-website/src/frontend/pages/generator.rs b/aep-schedule-website/src/frontend/pages/generator.rs
index cfc00c422508ff7de438a33d3faa50b92732fedf..52f0d6ba52b4fcf93dd9771ea5075f9b1d1040df 100644
--- a/aep-schedule-website/src/frontend/pages/generator.rs
+++ b/aep-schedule-website/src/frontend/pages/generator.rs
@@ -7,7 +7,13 @@ use aep_schedule_generator::data::group_sigle::SigleGroup;
 use leptos::*;
 
 #[derive(Clone, Copy)]
-pub struct SetModal(pub WriteSignal<Option<SigleGroup>>);
+pub struct SetModal(WriteSignal<Option<SigleGroup>>);
+
+impl SetModal {
+    pub fn from_context() -> WriteSignal<Option<SigleGroup>> {
+        use_context::<Self>().unwrap().0
+    }
+}
 
 #[derive(Clone, Copy)]
 pub struct FirstGenerationDone(pub RwSignal<bool>);
@@ -17,8 +23,6 @@ pub fn GeneratorPage() -> impl IntoView {
     let (hide, set_hide) = create_signal(false);
     let first_generation_done = create_rw_signal(false);
 
-    let (step, set_step) = create_signal(1);
-
     // Creates a reactive value to update the button
     let action = create_action(move |s: &SchedulesOptions| {
         let mut s = s.clone();
@@ -31,55 +35,16 @@ pub fn GeneratorPage() -> impl IntoView {
 
     let state = OptionState::default();
 
-    let section_error = create_rw_signal("".to_string());
-    let personal_error = create_rw_signal("".to_string());
-
-    let validate = move |state: OptionState| {
-        let mut options: SchedulesOptions = (&state).into();
-        if options.courses_to_take.is_empty() {
-            set_step.set(1);
-            return;
-        }
-        let mut impossible_courses = options.get_impossible_course().into_iter();
-        if let Some(first_impossible_course) = impossible_courses.next() {
-            let mut error = format!("Les sections des/du cours {}", first_impossible_course);
-            for impossible_course in impossible_courses {
-                error.push_str(", ");
-                error.push_str(&impossible_course);
-            }
-            error.push_str(" sont toutes fermées.");
-            section_error.set(error);
-            set_step.set(2);
-            return;
-        }
-        section_error.set("".to_string());
-        options.apply_personal_schedule();
-        let mut impossible_courses = options.get_impossible_course().into_iter();
-        if let Some(first_impossible_course) = impossible_courses.next() {
-            let mut error = format!("Les sections des/du cours {}", first_impossible_course);
-            for impossible_course in impossible_courses {
-                error.push_str(", ");
-                error.push_str(&impossible_course);
-            }
-            error.push_str(" sont en conflits avec les heures libres sélectionnées.");
-            personal_error.set(error);
-            set_step.set(3);
-            return;
-        }
-        personal_error.set("".to_string());
-        set_step.set(5);
-    };
-
     provide_context(state);
     provide_context(SetModal(set_modal));
     provide_context(FirstGenerationDone(first_generation_done));
 
     view! {
         <aside class="left-panel" class=("hide-left-panel", hide)>
-            <OptionsForms action validate step/>
+            <OptionsForms action/>
         </aside>
         <section class="right-panel">
-            <SchedulesComponent section_error personal_error action=action read_signal=action.value() step/>
+            <SchedulesComponent action=action read_signal=action.value()/>
         </section>
         <Notifications modal set_modal/>
         <button on:click=move |_| {set_hide(false)} id="go-back"><CaretDoubleRight weight=IconWeight::Regular size="3vh"/></button>