diff --git a/aep-schedule-generator/src/algorithm/generation.rs b/aep-schedule-generator/src/algorithm/generation.rs
index 88a0bf5f7ca09d5ba463bae98abab72f3fb73d60..cf57da95b64a0af3c99be1da25197073b677ab29 100644
--- a/aep-schedule-generator/src/algorithm/generation.rs
+++ b/aep-schedule-generator/src/algorithm/generation.rs
@@ -21,6 +21,11 @@ impl SchedulesOptions {
     // pub fn get_simple_conflict<'a>(&'a self) -> Option<Conflicts> {
 
     // }
+    pub fn apply_personal_schedule<'a>(&'a mut self) {
+        self.courses_to_take
+            .iter_mut()
+            .for_each(|c| c.apply_week_mask(&self.user_conflicts));
+    }
     pub fn get_impossible_course<'a>(&'a self) -> Vec<CompactString> {
         self.courses_to_take
             .iter()
diff --git a/aep-schedule-generator/src/algorithm/schedule.rs b/aep-schedule-generator/src/algorithm/schedule.rs
index c5367f9258f61183520feb284207eac0cc0df33d..339516f96c728e297e5660a8da5f1cc35a6c7768 100644
--- a/aep-schedule-generator/src/algorithm/schedule.rs
+++ b/aep-schedule-generator/src/algorithm/schedule.rs
@@ -10,7 +10,6 @@ use crate::data::{
         day::Day,
         hours::NO_HOUR,
         period::Period,
-        week::Week,
         weeks::Weeks,
     },
 };
@@ -74,7 +73,6 @@ impl<'a> ScheduleBuilder<'a> {
         &self,
         n: u8,
         min: f64,
-        user_conflicts: &Week<5>,
         options: EvaluationOption,
         new_course: TakenCourseBuilder,
     ) -> Option<Self> {
@@ -82,10 +80,6 @@ impl<'a> ScheduleBuilder<'a> {
         let mut is_cancelled = false;
         new_course.for_each_group(self.courses, |group| {
             for period in &group.periods {
-                if user_conflicts.user_conflict_in_day(period) {
-                    is_cancelled = true;
-                    return;
-                }
                 if new_schedule.week.conflict_in_day(period) {
                     new_schedule.conflicts += 1;
                     if new_schedule.conflicts > n {
diff --git a/aep-schedule-generator/src/algorithm/schedules.rs b/aep-schedule-generator/src/algorithm/schedules.rs
index 80cdc6a62d14529aa195ce442648f5216079d4c5..3dbf24433491a49dba1cfdf766e3c0a25554fdce 100644
--- a/aep-schedule-generator/src/algorithm/schedules.rs
+++ b/aep-schedule-generator/src/algorithm/schedules.rs
@@ -46,12 +46,11 @@ impl<'a> Schedules<'a> {
         };
         let min = self.get_min();
         let e = self.options.evaluation;
-        let c = self.options.user_conflicts;
         match &course.course_type {
             CourseType::LabOnly { lab_groups } => {
                 for lab_group in lab_groups.iter().filter(|g| g.open) {
                     let course = TakenCourseBuilder::new(i, GroupIndex::none(), lab_group.into());
-                    if let Some(schedule) = schedule.add_check_conflicts(n, min, &c, e, course) {
+                    if let Some(schedule) = schedule.add_check_conflicts(n, min, e, course) {
                         self.get_schedules_rec(schedule, n, i + 1);
                     }
                 }
@@ -59,7 +58,7 @@ impl<'a> Schedules<'a> {
             CourseType::TheoOnly { theo_groups } => {
                 for theo_group in theo_groups.iter().filter(|g| g.open) {
                     let course = TakenCourseBuilder::new(i, theo_group.into(), GroupIndex::none());
-                    if let Some(schedule) = schedule.add_check_conflicts(n, min, &c, e, course) {
+                    if let Some(schedule) = schedule.add_check_conflicts(n, min, e, course) {
                         self.get_schedules_rec(schedule, n, i + 1);
                     }
                 }
@@ -72,8 +71,7 @@ impl<'a> Schedules<'a> {
                     for lab_group in lab_groups.iter().filter(|g| g.open) {
                         let course =
                             TakenCourseBuilder::new(i, theo_group.into(), lab_group.into());
-                        if let Some(schedule) = schedule.add_check_conflicts(n, min, &c, e, course)
-                        {
+                        if let Some(schedule) = schedule.add_check_conflicts(n, min, e, course) {
                             self.get_schedules_rec(schedule, n, i + 1);
                         }
                     }
@@ -89,7 +87,7 @@ impl<'a> Schedules<'a> {
                     .zip(lab_groups.iter().filter(|g| g.open))
                 {
                     let course = TakenCourseBuilder::new(i, theo_group.into(), lab_group.into());
-                    if let Some(schedule) = schedule.add_check_conflicts(n, min, &c, e, course) {
+                    if let Some(schedule) = schedule.add_check_conflicts(n, min, e, course) {
                         self.get_schedules_rec(schedule, n, i + 1);
                     }
                 }
diff --git a/aep-schedule-generator/src/data/course.rs b/aep-schedule-generator/src/data/course.rs
index c523b628933742d5891062cf60162902e88fa50d..070ab8f88221f4a3a3f4f83f00c7f6eb562ff7aa 100644
--- a/aep-schedule-generator/src/data/course.rs
+++ b/aep-schedule-generator/src/data/course.rs
@@ -3,6 +3,7 @@ use super::{
     group::Group,
     group_index::GroupIndex,
     group_sigle::{GroupType, SigleGroup},
+    time::week::Week,
 };
 use compact_str::CompactString;
 use serde::{Deserialize, Serialize};
@@ -166,4 +167,24 @@ impl Course {
             CourseType::Linked { theo_groups, .. } => theo_groups.is_impossible(),
         }
     }
+    pub fn apply_week_mask(&mut self, week: &Week<5>) {
+        match &mut self.course_type {
+            CourseType::TheoOnly { theo_groups } => theo_groups.apply_week_mask(week),
+            CourseType::LabOnly { lab_groups } => lab_groups.apply_week_mask(week),
+            CourseType::Both {
+                theo_groups,
+                lab_groups,
+            } => {
+                theo_groups.apply_week_mask(week);
+                lab_groups.apply_week_mask(week);
+            }
+            CourseType::Linked {
+                theo_groups,
+                lab_groups,
+            } => {
+                theo_groups.apply_week_mask(week);
+                lab_groups.apply_week_mask(week);
+            }
+        }
+    }
 }
diff --git a/aep-schedule-generator/src/data/groups.rs b/aep-schedule-generator/src/data/groups.rs
index ebb8b460f2ea6a2a3f8987b8e0d07670f497d05f..f6fdc31c8568f14257655b20c36394c5e909b96d 100644
--- a/aep-schedule-generator/src/data/groups.rs
+++ b/aep-schedule-generator/src/data/groups.rs
@@ -2,6 +2,7 @@ use super::{
     group::Group,
     group_index::GroupIndex,
     group_sigle::{GroupType, SigleGroup},
+    time::week::Week,
 };
 use compact_str::CompactString;
 use serde::{Deserialize, Serialize};
@@ -71,6 +72,12 @@ impl Groups {
             .map(|g| SigleGroup::new(sigle.clone(), group_type, g.number))
             .collect()
     }
+
+    pub fn apply_week_mask(&mut self, week: &Week<5>) {
+        self.iter_mut()
+            .filter(|g| g.periods.iter().any(|p| week.user_conflict_in_day(p)))
+            .for_each(|g| g.open = false);
+    }
 }
 
 impl Index<GroupIndex> for Groups {
diff --git a/aep-schedule-generator/src/data/time/week.rs b/aep-schedule-generator/src/data/time/week.rs
index ec95e751d1e52fdb76320acdc845f5a6259748e4..6e741d399192853840ffe6f7a8d0f5c8dd486e51 100644
--- a/aep-schedule-generator/src/data/time/week.rs
+++ b/aep-schedule-generator/src/data/time/week.rs
@@ -8,6 +8,7 @@ use std::ops::Deref;
 pub struct Week<const N: usize>([Hours; N]);
 
 impl<const N: usize> Default for Week<N> {
+    #[inline]
     fn default() -> Self {
         Self([NO_HOUR; N])
     }
@@ -15,21 +16,29 @@ impl<const N: usize> Default for Week<N> {
 
 impl<const N: usize> Deref for Week<N> {
     type Target = [Hours; N];
+    #[inline]
     fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
 
 impl<const N: usize> Week<N> {
+    #[inline]
     pub fn new(week: [u64; N]) -> Self {
         Self(week.map(|d| Hours::from(d)))
     }
+
+    #[inline]
     pub fn add_period(&mut self, period: &Period) {
         self.0[period.day as usize] |= period.hours;
     }
+
+    #[inline]
     pub fn conflict_in_day(&self, period: &Period) -> bool {
         self.0[period.day as usize] & period.hours != NO_HOUR
     }
+
+    #[inline]
     pub fn user_conflict_in_day(&self, period: &Period) -> bool {
         if period.day as usize >= N {
             return false;
diff --git a/aep-schedule-website/src/frontend/components/options/form.rs b/aep-schedule-website/src/frontend/components/options/form.rs
index 7b63932797e55aace06c60d57e1cd16985f44124..4eee55cbc22648919a71820b9a0c19afc80befdb 100644
--- a/aep-schedule-website/src/frontend/components/options/form.rs
+++ b/aep-schedule-website/src/frontend/components/options/form.rs
@@ -12,12 +12,20 @@ use aep_schedule_generator::algorithm::{generation::SchedulesOptions, schedule::
 use leptos::*;
 
 #[component]
-pub fn OptionsForms(action: Action<SchedulesOptions, Vec<Schedule>>) -> impl IntoView {
+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();
 
     let first_generation_done: FirstGenerationDone = use_context().unwrap();
     let submit = move || {
-        if !first_generation_done.0.get() {
+        validate(state);
+        if !first_generation_done.0.get() || step.get() != 5 {
             return;
         }
         action.dispatch((&state).into());
diff --git a/aep-schedule-website/src/frontend/components/options/todo.rs b/aep-schedule-website/src/frontend/components/options/todo.rs
index be3cd949ea854b71ce485898a7914530af7ec4c4..88d9f108d506d88a00ff1c12c1caafe9dc4142f9 100644
--- a/aep-schedule-website/src/frontend/components/options/todo.rs
+++ b/aep-schedule-website/src/frontend/components/options/todo.rs
@@ -46,7 +46,10 @@ pub fn Step(
 }
 
 #[component]
-pub fn Todo(action: Action<SchedulesOptions, Vec<Schedule>>) -> impl IntoView {
+pub fn Todo(
+    action: Action<SchedulesOptions, Vec<Schedule>>,
+    step: ReadSignal<u8>,
+) -> impl IntoView {
     let state: OptionState = use_context().unwrap();
     let first_generation_done: FirstGenerationDone = use_context().unwrap();
 
@@ -55,27 +58,40 @@ pub fn Todo(action: Action<SchedulesOptions, Vec<Schedule>>) -> impl IntoView {
         action.dispatch((&state).into())
     };
 
-    let (step, set_step) = create_signal(3);
+    let disab = move || {
+        let step = step.get();
+        match step {
+            0..=4 => "disabled",
+            _ => "",
+        }
+    };
+
+    let bg_color = move || {
+        match step.get().cmp(&5) {
+            Ordering::Less => "flex transition-colors items-center justify-center w-10 h-10 border rounded-full",
+            Ordering::Greater | Ordering::Equal => "flex transition-colors items-center justify-center w-10 h-10 border rounded-full bg-green-400",
+        }
+    };
 
     view! {
         <div class="px-4 py-4 mx-auto">
             <div class="grid gap-6 row-gap-10">
                 <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="Forcer des heures libres" description="Sélectionnez une plage de temps à avoir absolument libre en pressant et relâchant sur votre horaire personnel."/>
-                    <Step n=3 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."/>
+                    <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."/>
+                    <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."/>
                     <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">
                         <div class="flex flex-col items-center mr-4">
                             <div>
-                                <div class="flex items-center justify-center w-10 h-10 border rounded-full">
+                                <div class=bg_color>
                                     <svg class="w-6 text-gray-600" stroke="currentColor" viewBox="0 0 24 24">
                                         <polyline fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="6,12 10,16 18,8"></polyline>
                                     </svg>
                                 </div>
                             </div>
                         </div>
-                        <button on:click=submit class="select-none rounded-lg bg-amber-500 py-1 text-lg font-sans font-semibold px-2 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>
+                        <button on:click=submit class="select-none rounded-lg bg-amber-500 py-1 text-lg font-sans font-semibold px-2 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" prop:disabled=disab disabled>"Générer les horaires"</button>
                     </div>
                 </div>
             </div>
diff --git a/aep-schedule-website/src/frontend/components/schedules.rs b/aep-schedule-website/src/frontend/components/schedules.rs
index d7ac67e761db96412e5d28e1e8832c33af622a1c..caf96eedf38a8b28b6afc0dcc3be35f89adb2993 100644
--- a/aep-schedule-website/src/frontend/components/schedules.rs
+++ b/aep-schedule-website/src/frontend/components/schedules.rs
@@ -8,6 +8,7 @@ use leptos::*;
 pub fn SchedulesComponent(
     read_signal: RwSignal<Option<Vec<Schedule>>>,
     action: Action<SchedulesOptions, Vec<Schedule>>,
+    step: ReadSignal<u8>,
 ) -> impl IntoView {
     view! {
         <Await
@@ -22,7 +23,7 @@ pub fn SchedulesComponent(
                     }
                 }).collect_view(),
                     None => view ! {
-                        <Todo action/>
+                        <Todo action step/>
                     }
                 }
             }
diff --git a/aep-schedule-website/src/frontend/pages/generator.rs b/aep-schedule-website/src/frontend/pages/generator.rs
index d03cd86e51523b1b991bff670a386142d7eeb8a7..783631efc44307d615d17f88997f90d3d7573e98 100644
--- a/aep-schedule-website/src/frontend/pages/generator.rs
+++ b/aep-schedule-website/src/frontend/pages/generator.rs
@@ -17,10 +17,13 @@ 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 s = s.clone();
+        let mut s = s.clone();
         set_hide(true);
+        s.apply_personal_schedule();
         async move { s.get_schedules().into_sorted_vec() }
     });
 
@@ -28,16 +31,34 @@ pub fn GeneratorPage() -> impl IntoView {
 
     let state = OptionState::default();
 
+    let validate = move |state: OptionState| {
+        let mut options: SchedulesOptions = (&state).into();
+        if options.courses_to_take.is_empty() {
+            set_step.set(1);
+            return;
+        }
+        if !options.get_impossible_course().is_empty() {
+            set_step.set(2);
+            return;
+        }
+        options.apply_personal_schedule();
+        if !options.get_impossible_course().is_empty() {
+            set_step.set(3);
+            return;
+        }
+        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=action/>
+            <OptionsForms action=action validate step/>
         </aside>
-        <section class="right-panel ">
-            <SchedulesComponent action=action read_signal=action.value()/>
+        <section class="right-panel">
+            <SchedulesComponent action=action read_signal=action.value() step/>
         </section>
         <Notifications modal set_modal/>
         <button on:click=move |_| {set_hide(false)} id="go-back"><CaretDoubleRight weight=IconWeight::Regular size="3vh"/></button>
diff --git a/aep-schedule-website/style/main.scss b/aep-schedule-website/style/main.scss
index 680a920ec0545427a62799f94fa3cd2c0e6dced9..93b18b391fe1eba19a57903329844b95343fe3b4 100644
--- a/aep-schedule-website/style/main.scss
+++ b/aep-schedule-website/style/main.scss
@@ -125,8 +125,8 @@ main {
 	display: flex;
 	flex-direction: column;
 	align-items: center;
-	gap: 2rem;
-	padding: 0.25rem;
+	gap: 3rem;
+	padding: 1rem;
 	background-color: $light-background;
 }
 
diff --git a/aep-schedule-website/style/options.scss b/aep-schedule-website/style/options.scss
index 3c170e17b50b6d3220cbeca143e80e718e6660e1..d92cd293a2754ec0b501e3a0eab54deed234905e 100644
--- a/aep-schedule-website/style/options.scss
+++ b/aep-schedule-website/style/options.scss
@@ -175,7 +175,7 @@
 }
 
 .selected-hour {
-  background-color: $background-color;
+  background-color: rgb(87, 104, 175);
 }
 
 .unselected-hour {