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>, can_vote: bool, }, DoneFetchingConfig { errors: Option>, min: usize, }, DoneFetchingTeachers { errors: Option>, teachers: Vec, }, 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>, min: usize, teachers: Option>, votes: HashMap>, } impl Component for StudentVote { type Message = Msg; type Properties = StudentVoteProps; fn create(ctx: &Context) -> Self { let client = graphql::client(Some(&ctx.props().token)).unwrap(); ctx.link().send_future(async move { let can_vote_response = post_graphql::( &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, 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::( &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::( &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) -> Html { if self.fetching { html! {

{ "Fetching..." }

} } else { let onsubmit = ctx.link().callback(|e: FocusEvent| { e.prevent_default(); Msg::Submit }); let mut teachers: Vec = vec![]; html! { <>

{ "Wähle deine Wunschmentoren aus:" }

{ 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! { <>
{ format!("{}. Wahl", i + 1) } { 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! {
}) } }) }
if i < self.min - 1 {
} } }) }
} } } }