221 lines
7.8 KiB
Rust
221 lines
7.8 KiB
Rust
use graphql_client::reqwest::post_graphql;
|
|
use std::collections::HashMap;
|
|
use yew::prelude::*;
|
|
|
|
use crate::components;
|
|
use crate::graphql;
|
|
|
|
pub enum Msg {
|
|
DoneFetchingCanVote {
|
|
errors: Option<Vec<String>>,
|
|
can_vote: bool,
|
|
},
|
|
DoneFetchingConfig {
|
|
errors: Option<Vec<String>>,
|
|
min: usize,
|
|
},
|
|
DoneFetchingTeachers {
|
|
errors: Option<Vec<String>>,
|
|
teachers: Vec<graphql::queries::teachers::teachers::TeachersTeachers>,
|
|
},
|
|
RadioSelect {
|
|
priority: usize,
|
|
teacher: i64,
|
|
},
|
|
Submit,
|
|
}
|
|
|
|
#[derive(Properties, PartialEq)]
|
|
pub struct StudentVoteProps {
|
|
pub token: String,
|
|
}
|
|
|
|
pub struct StudentVote {
|
|
fetching: bool,
|
|
can_vote: bool,
|
|
errors: Option<Vec<String>>,
|
|
min: usize,
|
|
teachers: Option<Vec<graphql::queries::teachers::teachers::TeachersTeachers>>,
|
|
votes: HashMap<usize, Option<i64>>,
|
|
}
|
|
|
|
impl Component for StudentVote {
|
|
type Message = Msg;
|
|
type Properties = StudentVoteProps;
|
|
|
|
fn create(ctx: &Context<Self>) -> Self {
|
|
let client = graphql::client(Some(&ctx.props().token)).unwrap();
|
|
ctx.link().send_future(async move {
|
|
let can_vote_response =
|
|
post_graphql::<graphql::queries::students_can_vote::StudentsCanVote, _>(
|
|
&client,
|
|
graphql::URL.as_str(),
|
|
graphql::queries::students_can_vote::students_can_vote::Variables,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
Msg::DoneFetchingCanVote {
|
|
errors: components::graphql_errors::convert(can_vote_response.errors),
|
|
can_vote: can_vote_response.data.unwrap().students_can_vote,
|
|
}
|
|
});
|
|
|
|
Self {
|
|
fetching: true,
|
|
can_vote: false,
|
|
errors: None,
|
|
min: 0,
|
|
teachers: None,
|
|
votes: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
match msg {
|
|
Msg::DoneFetchingCanVote { errors, can_vote } => {
|
|
self.errors = errors;
|
|
self.can_vote = can_vote;
|
|
|
|
let client = graphql::client(Some(&ctx.props().token)).unwrap();
|
|
ctx.link().send_future(async move {
|
|
let response = post_graphql::<graphql::queries::config::Config, _>(
|
|
&client,
|
|
graphql::URL.as_str(),
|
|
graphql::queries::config::config::Variables,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
Msg::DoneFetchingConfig {
|
|
errors: components::graphql_errors::convert(response.errors),
|
|
min: response
|
|
.data
|
|
.unwrap()
|
|
.config
|
|
.minimum_teacher_selection_count as usize,
|
|
}
|
|
});
|
|
|
|
true
|
|
}
|
|
Msg::DoneFetchingConfig { errors, min } => {
|
|
self.errors = errors;
|
|
self.min = min;
|
|
|
|
let client = graphql::client(Some(&ctx.props().token)).unwrap();
|
|
ctx.link().send_future(async move {
|
|
let response = post_graphql::<graphql::queries::teachers::Teachers, _>(
|
|
&client,
|
|
graphql::URL.as_str(),
|
|
graphql::queries::teachers::teachers::Variables,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
Msg::DoneFetchingTeachers {
|
|
errors: components::graphql_errors::convert(response.errors),
|
|
teachers: response.data.unwrap().teachers,
|
|
}
|
|
});
|
|
|
|
true
|
|
}
|
|
Msg::DoneFetchingTeachers { errors, teachers } => {
|
|
self.fetching = false;
|
|
self.errors = errors;
|
|
self.teachers = Some(teachers);
|
|
true
|
|
}
|
|
Msg::RadioSelect { priority, teacher } => {
|
|
self.votes.insert(priority, Some(teacher));
|
|
for (p, t) in self.votes.iter_mut() {
|
|
if *p > priority && *t == Some(teacher) {
|
|
*t = None;
|
|
}
|
|
}
|
|
|
|
true
|
|
}
|
|
Msg::Submit => {
|
|
log::debug!("{:?}", self.votes);
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
if self.fetching {
|
|
html! {
|
|
<p>{ "Fetching..." }</p>
|
|
}
|
|
} else {
|
|
let onsubmit = ctx.link().callback(|e: FocusEvent| {
|
|
e.prevent_default();
|
|
|
|
Msg::Submit
|
|
});
|
|
let mut teachers: Vec<i64> = vec![];
|
|
|
|
html! {
|
|
<>
|
|
<h3>{ "Wähle deine Wunschmentoren aus:" }</h3>
|
|
<form {onsubmit}>
|
|
{ for (0..self.min).map(|i| {
|
|
let curr_t = self.votes.get(&i);
|
|
if let Some(te) = curr_t {
|
|
if let Some(t) = te {
|
|
teachers.push(*t);
|
|
}
|
|
}
|
|
let name = format!("mentors_{}", i);
|
|
|
|
html! {
|
|
<>
|
|
<fieldset>
|
|
<legend>{ format!("{}. Wahl", i + 1) }</legend>
|
|
|
|
{ for self.teachers.as_ref().unwrap().iter().enumerate().filter_map(|(j, t)| {
|
|
let checked = curr_t == Some(&Some(t.id));
|
|
|
|
if teachers.contains(&t.id) && !checked {
|
|
None
|
|
} else {
|
|
let id = format!("{}_{}", name, j);
|
|
let teacher_id = t.id;
|
|
let onchange = ctx.link().callback(move |_| Msg::RadioSelect { priority: i, teacher: teacher_id });
|
|
|
|
Some(html! {
|
|
<div>
|
|
<input
|
|
type="radio"
|
|
id={id.to_owned()}
|
|
name={name.to_owned()}
|
|
value={t.user.name.to_owned()}
|
|
required=true
|
|
{onchange}
|
|
{checked}
|
|
/>
|
|
<label for={id}>{ &t.user.name }</label>
|
|
</div>
|
|
})
|
|
}
|
|
}) }
|
|
</fieldset>
|
|
if i < self.min - 1 {
|
|
<br />
|
|
}
|
|
</>
|
|
}
|
|
}) }
|
|
|
|
<div>
|
|
<button type="submit">{ "Submit" }</button>
|
|
</div>
|
|
</form>
|
|
</>
|
|
}
|
|
}
|
|
}
|
|
}
|