Allows for wrong answers, changed some names and added correct/wroung counters at the top
parent
460b3e2790
commit
4d984cd2e3
|
@ -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) {
|
||||||
|
|
61
src/main.rs
61
src/main.rs
|
@ -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" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue