Allows for wrong answers, changed some names and added correct/wroung counters at the top

master
Wynd 2025-06-15 15:16:03 +03:00
parent 460b3e2790
commit 4d984cd2e3
2 changed files with 99 additions and 15 deletions

View File

@ -1,20 +1,47 @@
:root { :root {
--text: white;
--correct: limegreen; --correct: limegreen;
--correct-shadow: green; --correct-shadow: green;
--fail: crimson;
--fail-shadow: red;
--hover: gray; --hover: gray;
--selection: goldenrod; --selection: goldenrod;
--selection-shadow: gold;
} }
body { body {
background-color: #0f1116; background-color: #0f1116;
color: #ffffff; color: var(--text);
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
margin: 0px; margin: 0px;
overflow-x: hidden;
} }
#counter { #counter {
margin: 10px; margin: 10px;
font-size: 20px; font-size: 20px;
> div {
display: inline-block;
&.correct {
color: var(--correct);
text-shadow: var(--correct-shadow) 0px 0px 30px;
}
&.wrong {
color: var(--fail);
text-shadow: var(--fail-shadow) 0px 0px 30px;
}
&:not(:last-child)::after {
color: var(--text);
content: "/";
}
}
} }
#result { #result {
@ -25,8 +52,6 @@ body {
margin: auto; margin: auto;
text-align: center; text-align: center;
line-height: 1; line-height: 1;
color: var(--correct);
text-shadow: var(--correct-shadow) 1px 1px 30px;
opacity: 0; opacity: 0;
user-select: none; user-select: none;
@ -34,6 +59,16 @@ body {
display: block; display: block;
animation: 200ms fade-in forwards; animation: 200ms fade-in forwards;
} }
&.correct {
color: var(--correct);
text-shadow: var(--correct-shadow) 0px 0px 30px;
}
&.wrong {
color: var(--fail);
text-shadow: var(--fail-shadow) 0px 0px 30px;
}
} }
@keyframes fade-in { @keyframes fade-in {
@ -56,8 +91,16 @@ form {
user-select: none; user-select: none;
h1 { h1 {
&.success { text-wrap: balance;
&.correct {
color: var(--correct); color: var(--correct);
text-shadow: var(--correct-shadow) 0px 0px 30px;
}
&.wrong {
color: var(--fail);
text-shadow: var(--fail-shadow) 0px 0px 30px;
} }
} }
@ -70,9 +113,11 @@ form {
align-self: center; align-self: center;
box-sizing: border-box; box-sizing: border-box;
border: solid 2px unset; border: solid 2px unset;
text-wrap: balance;
&.selected { &.selected {
border: solid 2px var(--selection); border: solid 2px var(--selection);
box-shadow: 0px 0px 13px -5px var(--selection-shadow);
} }
&:hover:not(.selected) { &:hover:not(.selected) {

View File

@ -85,22 +85,47 @@ pub fn QuestionForm() -> Element {
let total_questions = QUESTIONS.len(); let total_questions = QUESTIONS.len();
let current_question = use_memo(move || questions().len()); let current_question = use_memo(move || questions().len());
let left_questions = use_memo(move || total_questions - current_question()); let left_questions = use_memo(move || total_questions - current_question());
let mut correct_questions = use_signal(|| 0);
let mut wrong_questions = use_signal(|| 0);
let mut success_animation = use_signal(|| false); let mut correct_animation = use_signal(|| false);
let mut wrong_animation = use_signal(|| false);
use_future(move || async move { use_future(move || async move {
loop { loop {
tokio::time::sleep(Duration::from_millis(400)).await; tokio::time::sleep(Duration::from_millis(400)).await;
if success_animation() { let is_correct = correct_animation();
let is_wrong = wrong_animation();
if is_correct || is_wrong {
tokio::time::sleep(Duration::from_millis(600)).await; tokio::time::sleep(Duration::from_millis(600)).await;
success_animation.set(false);
// Uncheck all the answers
current().answers.iter_mut().for_each(|a| a.checked = false); current().answers.iter_mut().for_each(|a| a.checked = false);
let mut correct_questions_lock = correct_questions.write();
let mut wrong_questions_lock = wrong_questions.write();
// Get a new question or reroll the list
if !questions().is_empty() { if !questions().is_empty() {
current.set(questions.remove(0)); current.set(questions.remove(0));
// Update the correct/wrong counters
if is_correct {
*correct_questions_lock += 1;
} else if is_wrong {
*wrong_questions_lock += 1;
}
} else { } else {
questions.set(get_questions()); questions.set(get_questions());
current.set(questions.remove(0)); current.set(questions.remove(0));
*correct_questions_lock = 0;
*wrong_questions_lock = 0;
} }
// Reset animation flags
correct_animation.set(false);
wrong_animation.set(false);
} }
} }
}); });
@ -116,24 +141,34 @@ pub fn QuestionForm() -> Element {
}); });
rsx! { rsx! {
ResultPopup { is_visible: success_animation }, ResultPopup { is_correct: correct_animation, is_wrong: wrong_animation },
div { div {
id: "counter", id: "counter",
"{left_questions}/{total_questions}" div { "{left_questions}" }
div {
class: "correct",
"{correct_questions}"
}
div {
class: "wrong",
"{wrong_questions}"
}
div { "{total_questions}" }
}, },
form { form {
id: "form", id: "form",
onsubmit: move |_| { onsubmit: move |_| {
if actual_correct() == total_correct() { if actual_correct() == total_correct() {
success_animation.set(true); correct_animation.set(true);
} }
else { else {
wrong_animation.set(true);
} }
}, },
h1 { h1 {
class: if success_animation() { "success" }, class: if correct_animation() { "correct" },
class: if wrong_animation() { "wrong" },
"{current().message}" "{current().message}"
} }
{ answer_buttons } { answer_buttons }
@ -192,14 +227,18 @@ pub fn AnswerCheckbox(current: Signal<Question>, id: usize) -> Element {
} }
#[component] #[component]
pub fn ResultPopup(is_visible: Signal<bool>) -> Element { pub fn ResultPopup(is_correct: Signal<bool>, is_wrong: Signal<bool>) -> Element {
let is_visible = use_memo(move || is_visible()); let is_correct = use_memo(move || is_correct());
let is_wrong = use_memo(move || is_wrong());
let is_visible = use_memo(move || is_correct() || is_wrong());
rsx! { rsx! {
div { div {
id: "result", id: "result",
class: if is_visible() { "visible" }, class: if is_visible() { "visible" },
"" class: if is_correct() { "correct" },
class: if is_wrong() { "wrong" },
if is_correct() { "" } else { "X" }
} }
} }
} }