More data on exams page
This commit is contained in:
1 parent
7ad44110c3
commit
496f246125
1 file changed
+89
-11
+89
-11
@@ -1,6 +1,6 @@
|
|||||||
use crate::app::AppState;
|
use crate::app::AppState;
|
||||||
use crate::data::Id;
|
use crate::data::Id;
|
||||||
use crate::data::entities::{DeckSettings, EntityHandle, Exam, ExamEntry};
|
use crate::data::entities::{DeckSettings, EntityHandle, Exam, ExamEntry, WordData};
|
||||||
use crate::data::repositories::{BatchedRepository, Repository};
|
use crate::data::repositories::{BatchedRepository, Repository};
|
||||||
use crate::navigation::Page::PreviousPage;
|
use crate::navigation::Page::PreviousPage;
|
||||||
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||||
@@ -9,11 +9,18 @@ use crate::pages::exam::ExamState;
|
|||||||
use crate::pages::exams::ExamsMessage::*;
|
use crate::pages::exams::ExamsMessage::*;
|
||||||
use crate::pages::repetitions::Style;
|
use crate::pages::repetitions::Style;
|
||||||
use crate::push_error;
|
use crate::push_error;
|
||||||
use crate::styling::{BUTTON_RADIUS, DEFAULT_SPACING, HALF_SPACING, back_overlay, cta_button};
|
use crate::styling::{
|
||||||
|
BUTTON_RADIUS, DEFAULT_SPACING, HALF_SPACING, QUARTER_SPACING, back_overlay, cta_button,
|
||||||
|
};
|
||||||
use crate::{jl_button, push_error_task};
|
use crate::{jl_button, push_error_task};
|
||||||
use chrono::{Local, Utc};
|
use chrono::{Local, Utc};
|
||||||
use iced::widget::button::Status;
|
use iced::widget::button::Status;
|
||||||
use iced::widget::{Column, button, center_x, column, container, row, rule, scrollable, space, text, tooltip};
|
use iced::widget::container::bordered_box;
|
||||||
|
use iced::widget::space::horizontal;
|
||||||
|
use iced::widget::{
|
||||||
|
Column, button, center, center_x, column, container, row, rule, scrollable, space, text,
|
||||||
|
tooltip,
|
||||||
|
};
|
||||||
use iced::{Element, Task};
|
use iced::{Element, Task};
|
||||||
use iced_core::Alignment::*;
|
use iced_core::Alignment::*;
|
||||||
use iced_core::Length::{Fill, FillPortion};
|
use iced_core::Length::{Fill, FillPortion};
|
||||||
@@ -46,7 +53,11 @@ impl NavigatedPage<ExamsMessage> for ExamsState {
|
|||||||
if let Some(selected_exam_id) = self.selected_exam_id
|
if let Some(selected_exam_id) = self.selected_exam_id
|
||||||
&& GotoExam == *message
|
&& GotoExam == *message
|
||||||
{
|
{
|
||||||
return Some(Page::Exam(ExamState::new(selected_exam_id.id, self.deck.clone(), &self.state)));
|
return Some(Page::Exam(ExamState::new(
|
||||||
|
selected_exam_id.id,
|
||||||
|
self.deck.clone(),
|
||||||
|
&self.state,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -90,7 +101,7 @@ impl NavigatedPage<ExamsMessage> for ExamsState {
|
|||||||
back_overlay(
|
back_overlay(
|
||||||
column![
|
column![
|
||||||
text(format!("Экзамены для колоды {}", self.deck.name)),
|
text(format!("Экзамены для колоды {}", self.deck.name)),
|
||||||
row![row![
|
row![
|
||||||
column![
|
column![
|
||||||
scrollable(self.exams_list()).height(Fill),
|
scrollable(self.exams_list()).height(Fill),
|
||||||
jl_button!("Добавить").width(Fill).on_press(CreateExam),
|
jl_button!("Добавить").width(Fill).on_press(CreateExam),
|
||||||
@@ -98,7 +109,7 @@ impl NavigatedPage<ExamsMessage> for ExamsState {
|
|||||||
.spacing(DEFAULT_SPACING)
|
.spacing(DEFAULT_SPACING)
|
||||||
.width(FillPortion(1)),
|
.width(FillPortion(1)),
|
||||||
self.selected_exam_view(),
|
self.selected_exam_view(),
|
||||||
]]
|
].spacing(DEFAULT_SPACING)
|
||||||
]
|
]
|
||||||
.into(),
|
.into(),
|
||||||
Back,
|
Back,
|
||||||
@@ -172,7 +183,13 @@ impl ExamsState {
|
|||||||
|
|
||||||
for (handle, deck) in self.exams.iter() {
|
for (handle, deck) in self.exams.iter() {
|
||||||
column = column.push(
|
column = column.push(
|
||||||
jl_button!(text!("{}", &deck.timestamp.with_timezone(&Local).format("%d/%m/%Y %H:%M")))
|
jl_button!(text!(
|
||||||
|
"{}",
|
||||||
|
&deck
|
||||||
|
.timestamp
|
||||||
|
.with_timezone(&Local)
|
||||||
|
.format("%d/%m/%Y %H:%M")
|
||||||
|
))
|
||||||
.on_press_with(move || SelectExam(*handle))
|
.on_press_with(move || SelectExam(*handle))
|
||||||
.style(move |_x: &Theme, status: Status| Style {
|
.style(move |_x: &Theme, status: Status| Style {
|
||||||
background: if status == Status::Hovered {
|
background: if status == Status::Hovered {
|
||||||
@@ -180,7 +197,11 @@ impl ExamsState {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
text_color: if deck.finished() { _x.palette().success } else { _x.palette().primary},
|
text_color: if deck.finished() {
|
||||||
|
_x.palette().success
|
||||||
|
} else {
|
||||||
|
_x.palette().primary
|
||||||
|
},
|
||||||
border: Border {
|
border: Border {
|
||||||
color: Default::default(),
|
color: Default::default(),
|
||||||
width: 0.0,
|
width: 0.0,
|
||||||
@@ -199,7 +220,9 @@ impl ExamsState {
|
|||||||
return column![
|
return column![
|
||||||
center_x(text!(
|
center_x(text!(
|
||||||
"Экзамен от {}",
|
"Экзамен от {}",
|
||||||
exam.timestamp.with_timezone(&Local).format("%d/%m/%Y %H:%M")
|
exam.timestamp
|
||||||
|
.with_timezone(&Local)
|
||||||
|
.format("%d/%m/%Y %H:%M")
|
||||||
)),
|
)),
|
||||||
row![text!("{} карточек", exam.total), Self::exam_bar(exam)]
|
row![text!("{} карточек", exam.total), Self::exam_bar(exam)]
|
||||||
.height(30)
|
.height(30)
|
||||||
@@ -284,7 +307,35 @@ impl ExamsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exam_finished_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
fn exam_finished_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
||||||
column![].spacing(DEFAULT_SPACING).into()
|
let result = (exam.answered as f64 / exam.total as f64 * 1000.0).round() / 10.0;
|
||||||
|
let words_repo = self.state.dictionary.read();
|
||||||
|
column![
|
||||||
|
center_x(text!("Итоговый результат: {}%", result).size(28)),
|
||||||
|
row![
|
||||||
|
Self::words_list(
|
||||||
|
"Правильно",
|
||||||
|
exam.answered_list
|
||||||
|
.iter()
|
||||||
|
.map(|handle| words_repo.get_ref_static(*handle).unwrap())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.as_slice()
|
||||||
|
)
|
||||||
|
.width(Fill),
|
||||||
|
Self::words_list(
|
||||||
|
"Не получилось",
|
||||||
|
exam.unknows_list
|
||||||
|
.iter()
|
||||||
|
.map(|handle| words_repo.get_ref_static(*handle).unwrap())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.as_slice()
|
||||||
|
)
|
||||||
|
.width(Fill)
|
||||||
|
]
|
||||||
|
.width(Fill)
|
||||||
|
.spacing(QUARTER_SPACING)
|
||||||
|
]
|
||||||
|
.spacing(DEFAULT_SPACING)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exam_ongoing_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
fn exam_ongoing_view(&self, exam: &ExamExtended) -> Element<'_, ExamsMessage> {
|
||||||
@@ -295,6 +346,26 @@ impl ExamsState {
|
|||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn words_list<'a>(name: &str, words: &[&WordData]) -> Column<'a, ExamsMessage> {
|
||||||
|
let mut column = column![];
|
||||||
|
for word in words {
|
||||||
|
let container = container(
|
||||||
|
column![text!("{}", word.key), text!("{}", word.value)].padding(QUARTER_SPACING),
|
||||||
|
)
|
||||||
|
.width(Fill)
|
||||||
|
.style(bordered_box);
|
||||||
|
column = column.push(container);
|
||||||
|
}
|
||||||
|
column![
|
||||||
|
text!("{}", name),
|
||||||
|
scrollable(row![
|
||||||
|
column.spacing(QUARTER_SPACING),
|
||||||
|
horizontal().width(DEFAULT_SPACING)
|
||||||
|
])
|
||||||
|
]
|
||||||
|
.align_x(Center)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExamExtended {
|
struct ExamExtended {
|
||||||
@@ -302,6 +373,8 @@ struct ExamExtended {
|
|||||||
total: u32,
|
total: u32,
|
||||||
answered: u32,
|
answered: u32,
|
||||||
unknown: u32,
|
unknown: u32,
|
||||||
|
answered_list: Vec<EntityHandle<WordData>>,
|
||||||
|
unknows_list: Vec<EntityHandle<WordData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExamExtended {
|
impl ExamExtended {
|
||||||
@@ -310,6 +383,8 @@ impl ExamExtended {
|
|||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
let mut answered = 0;
|
let mut answered = 0;
|
||||||
let mut unknown = 0;
|
let mut unknown = 0;
|
||||||
|
let mut answered_list = Vec::with_capacity(128);
|
||||||
|
let mut unknows_list = Vec::with_capacity(128);
|
||||||
entries
|
entries
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|e| e.exam_id == exam.id)
|
.filter(|e| e.exam_id == exam.id)
|
||||||
@@ -320,8 +395,10 @@ impl ExamExtended {
|
|||||||
Some(s) => {
|
Some(s) => {
|
||||||
if s {
|
if s {
|
||||||
answered += 1;
|
answered += 1;
|
||||||
|
answered_list.push(EntityHandle::from_id(e.word_id));
|
||||||
} else {
|
} else {
|
||||||
unknown += 1;
|
unknown += 1;
|
||||||
|
unknows_list.push(EntityHandle::from_id(e.word_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,10 +406,11 @@ impl ExamExtended {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
exam,
|
exam,
|
||||||
|
|
||||||
total,
|
total,
|
||||||
answered,
|
answered,
|
||||||
unknown,
|
unknown,
|
||||||
|
answered_list,
|
||||||
|
unknows_list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn solved(&self) -> u32 {
|
fn solved(&self) -> u32 {
|
||||||
|
|||||||
Reference in new issue
Block a user