Initial reports page at the end
parent
c2435f4c24
commit
46acb8c196
|
@ -25,6 +25,44 @@ body {
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#report {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 5vh;
|
||||
|
||||
> p {
|
||||
font-size: 2vw;
|
||||
|
||||
&.correct {
|
||||
color: var(--correct);
|
||||
text-shadow: var(--correct-shadow) 0px 0px 30px;
|
||||
}
|
||||
|
||||
&.wrong {
|
||||
color: var(--fail);
|
||||
text-shadow: var(--fail-shadow) 0px 0px 30px;
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
> button {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#counter {
|
||||
margin: 10px;
|
||||
font-size: 20px;
|
||||
|
@ -99,11 +137,11 @@ form {
|
|||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 24px;
|
||||
font-size: 1vw;
|
||||
user-select: none;
|
||||
|
||||
h1 {
|
||||
font-size: 3vw;
|
||||
font-size: 2vw;
|
||||
text-wrap: balance;
|
||||
|
||||
&.correct {
|
||||
|
@ -119,9 +157,9 @@ form {
|
|||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
height: 10vh;
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
margin-top: 3vh;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
box-sizing: border-box;
|
||||
|
@ -143,8 +181,10 @@ form {
|
|||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> input[type="submit"] {
|
||||
button,
|
||||
input[type="submit"] {
|
||||
margin-top: 40px;
|
||||
height: 70px;
|
||||
background-color: transparent;
|
||||
|
@ -156,10 +196,17 @@ form {
|
|||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 540px) {
|
||||
#report {
|
||||
> p {
|
||||
font-size: 6vw;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
font-size: 4vw;
|
||||
|
||||
h1 {
|
||||
font-size: 5vw;
|
||||
}
|
||||
|
@ -172,12 +219,6 @@ form {
|
|||
|
||||
@media (hover: hover) {
|
||||
form {
|
||||
> input[type="submit"]:hover {
|
||||
font-size: 48px;
|
||||
color: var(--selection);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
> div {
|
||||
&:hover:not(.selected) {
|
||||
border: solid 1px var(--hover);
|
||||
|
@ -189,4 +230,11 @@ form {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
button:hover,
|
||||
input[type="submit"]:hover {
|
||||
font-size: 48px;
|
||||
color: var(--selection);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
178
src/main.rs
178
src/main.rs
|
@ -4,7 +4,7 @@ use std::{sync::OnceLock, time::Duration};
|
|||
use async_std::task::sleep;
|
||||
#[cfg(feature = "desktop")]
|
||||
use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus::{logger::tracing, prelude::*};
|
||||
#[cfg(feature = "bundled")]
|
||||
use include_dir::{Dir, include_dir};
|
||||
use models::{Question, Questions};
|
||||
|
@ -118,22 +118,60 @@ fn main() {
|
|||
fn App() -> Element {
|
||||
let questions = get_rand_questions();
|
||||
|
||||
let correct_questions = use_signal(|| 0);
|
||||
let wrong_questions = use_signal(|| 0);
|
||||
|
||||
let has_finished = use_signal(|| false);
|
||||
let has_restart = use_signal(|| false);
|
||||
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: MAIN_CSS }
|
||||
if !questions.is_empty() {
|
||||
QuestionForm { questions }
|
||||
p { "{has_restart}" }
|
||||
if !questions.is_empty() && !has_finished() {
|
||||
QuestionForm { questions, correct_questions, wrong_questions, has_finished, has_restart }
|
||||
}
|
||||
else if has_finished() {
|
||||
Report {
|
||||
questions,
|
||||
correct_questions: correct_questions(),
|
||||
wrong_questions: wrong_questions(),
|
||||
has_restart,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
#[component]
|
||||
pub fn QuestionForm(questions: Vec<Question>) -> Element {
|
||||
pub fn QuestionForm(
|
||||
questions: Vec<Question>,
|
||||
correct_questions: Signal<i32>,
|
||||
wrong_questions: Signal<i32>,
|
||||
has_finished: Signal<bool>,
|
||||
has_restart: Signal<bool>,
|
||||
) -> Element {
|
||||
let mut questions = use_signal(|| questions);
|
||||
let mut current = use_signal(move || questions.remove(0));
|
||||
let mut current = use_signal(move || questions().remove(0));
|
||||
|
||||
// use_effect(move || {
|
||||
// let mut has_restart_lock = has_restart.write();
|
||||
// tracing::info!("called new questions effect {}", *has_restart_lock);
|
||||
// if *has_restart_lock {
|
||||
// tracing::info!("actually passing effect");
|
||||
// let mut questions_lock = questions.write();
|
||||
//
|
||||
// *questions_lock = get_rand_questions();
|
||||
// current.set(questions_lock.remove(0));
|
||||
//
|
||||
// correct_questions.set(0);
|
||||
// wrong_questions.set(0);
|
||||
// *has_restart_lock = false;
|
||||
// has_finished.set(false);
|
||||
// }
|
||||
// });
|
||||
|
||||
let total_correct = use_memo(move || {
|
||||
current
|
||||
.read()
|
||||
current()
|
||||
.answers
|
||||
.iter()
|
||||
.filter(|a| a.is_correct.unwrap_or_default())
|
||||
|
@ -155,12 +193,6 @@ pub fn QuestionForm(questions: Vec<Question>) -> Element {
|
|||
correctly_checked.saturating_sub(incorrectly_checked)
|
||||
});
|
||||
|
||||
let total_questions = get_questions().len();
|
||||
let current_question = use_memo(move || questions().len());
|
||||
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 correct_animation = use_signal(|| false);
|
||||
let mut wrong_animation = use_signal(|| false);
|
||||
|
||||
|
@ -173,15 +205,21 @@ pub fn QuestionForm(questions: Vec<Question>) -> Element {
|
|||
if is_correct || is_wrong {
|
||||
sleep(Duration::from_millis(600)).await;
|
||||
|
||||
// Uncheck all the answers
|
||||
current().answers.iter_mut().for_each(|a| a.checked = false);
|
||||
|
||||
let mut current_lock = current.write();
|
||||
let mut correct_questions_lock = correct_questions.write();
|
||||
let mut wrong_questions_lock = wrong_questions.write();
|
||||
let mut questions_lock = questions.write();
|
||||
let mut has_finished_lock = has_finished.write();
|
||||
|
||||
// Uncheck all the answers
|
||||
current_lock
|
||||
.answers
|
||||
.iter_mut()
|
||||
.for_each(|a| a.checked = false);
|
||||
|
||||
// Get a new question or reroll the list
|
||||
if !questions().is_empty() {
|
||||
current.set(questions.remove(0));
|
||||
if !questions_lock.is_empty() {
|
||||
*current_lock = questions_lock.remove(0);
|
||||
|
||||
// Update the correct/wrong counters
|
||||
if is_correct {
|
||||
|
@ -189,12 +227,10 @@ pub fn QuestionForm(questions: Vec<Question>) -> Element {
|
|||
} else if is_wrong {
|
||||
*wrong_questions_lock += 1;
|
||||
}
|
||||
} else {
|
||||
questions.set(get_rand_questions());
|
||||
current.set(questions.remove(0));
|
||||
|
||||
*correct_questions_lock = 0;
|
||||
*wrong_questions_lock = 0;
|
||||
if questions_lock.is_empty() {
|
||||
*has_finished_lock = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset animation flags
|
||||
|
@ -215,20 +251,8 @@ pub fn QuestionForm(questions: Vec<Question>) -> Element {
|
|||
});
|
||||
|
||||
rsx! {
|
||||
ResultPopup { is_correct: correct_animation, is_wrong: wrong_animation },
|
||||
div {
|
||||
id: "counter",
|
||||
div { "{left_questions}" }
|
||||
div {
|
||||
class: "correct",
|
||||
"{correct_questions}"
|
||||
}
|
||||
div {
|
||||
class: "wrong",
|
||||
"{wrong_questions}"
|
||||
}
|
||||
div { "{total_questions}" }
|
||||
},
|
||||
Result { is_correct: correct_animation(), is_wrong: wrong_animation() },
|
||||
Info { questions, correct_questions, wrong_questions },
|
||||
form {
|
||||
id: "form",
|
||||
onsubmit: move |_| {
|
||||
|
@ -303,20 +327,84 @@ pub fn AnswerCheckbox(current: Signal<Question>, id: usize) -> Element {
|
|||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
#[component]
|
||||
pub fn ResultPopup(is_correct: Signal<bool>, is_wrong: Signal<bool>) -> Element {
|
||||
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());
|
||||
pub fn Result(is_correct: bool, is_wrong: bool) -> Element {
|
||||
let is_visible = is_correct || is_wrong;
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
id: "result",
|
||||
class: if is_visible() { "visible" },
|
||||
class: if is_visible { "visible" },
|
||||
|
||||
div {
|
||||
class: if is_correct() { "correct" },
|
||||
class: if is_wrong() { "wrong" },
|
||||
if is_correct() { "✓" } else { "X" }
|
||||
class: if is_correct { "correct" },
|
||||
class: if is_wrong { "wrong" },
|
||||
if is_correct { "✓" } else { "X" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
#[component]
|
||||
pub fn Info(
|
||||
questions: Signal<Vec<Question>>,
|
||||
correct_questions: Signal<i32>,
|
||||
wrong_questions: Signal<i32>,
|
||||
) -> Element {
|
||||
let total_questions = get_questions().len();
|
||||
let current_question = use_memo(move || questions().len());
|
||||
let left_questions = use_memo(move || total_questions - current_question());
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
id: "counter",
|
||||
|
||||
div { "{left_questions}" }
|
||||
div {
|
||||
class: "correct",
|
||||
"{correct_questions}"
|
||||
}
|
||||
div {
|
||||
class: "wrong",
|
||||
"{wrong_questions}"
|
||||
}
|
||||
div { "{total_questions}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Report(
|
||||
questions: Vec<Question>,
|
||||
correct_questions: i32,
|
||||
wrong_questions: i32,
|
||||
has_restart: Signal<bool>,
|
||||
) -> Element {
|
||||
let questions_size = questions.len();
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
id: "report",
|
||||
|
||||
p { "Questions: {questions_size}" },
|
||||
p {
|
||||
class: "correct",
|
||||
"Correct: {correct_questions}"
|
||||
},
|
||||
p {
|
||||
class: "wrong",
|
||||
"Wrong: {wrong_questions}"
|
||||
},
|
||||
div {
|
||||
button {
|
||||
// onclick: move |_| {
|
||||
// *has_restart.write() = true;
|
||||
// },
|
||||
"Restart"
|
||||
},
|
||||
button {
|
||||
"Restart with only wrong questions"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue