cds-web/front/src/components/list_groups.rs

493 lines
18 KiB
Rust

use gloo_net::http::Request;
use gloo_net::Error;
use gloo_storage::errors::StorageError;
use gloo_storage::{LocalStorage, Storage};
use patternfly_yew::{
ActionGroup, Button, Card, Color, Flex, FlexModifier, Form, FormGroup, FormGroupValidated, Gallery, Icon, Label, Modal, ModalVariant, TextInput, Title, ToFlexItems,
ToastViewer, Validator, ValidationContext, ValidationResult, Variant, WithBreakpointExt,
};
use yew::prelude::*;
#[derive(Default)]
pub struct ListGroups {
/// Id de l'utilisateur connecté
id_user: String,
/// Ses groupes
groups: Vec<Group>,
/// Les groupes où il n'y est pas
free_groups: Vec<Group>,
/// Nombre de groupes à afficher
nb_show: usize,
/// Groupe choisi dans la fenetre "rejoindre"
selected_group: usize,
/// Quel fenetre modal on affiche
modal: ModalGroup,
/// Le groupe à créer
new_group: Option<Group>,
/// Nom du nouveau groupe
new_name: String,
/// Nom du jeu
form_game: String,
/// Jeu pour le nouveau groupe.
new_game: Option<Game>,
}
#[derive(PartialEq, Properties)]
pub struct PropGroups {
pub id: String,
}
/// Quel modal il faut afficher
enum ModalGroup {
None,
Create,
Join,
}
impl Default for ModalGroup {
fn default() -> Self {
Self::None
}
}
#[derive(Eq, PartialEq)]
pub enum MsgListGroups {
/// Rafraichi la page
Refresh,
/// Tous les groupes ont été récupéré
Done(Vec<Group>),
/// Tous les groupes sans l'utilisateur ont été récupéré
DoneFree(Vec<Group>),
/// Quitte un groupe
Leave(usize),
FinishLeave(usize),
/// Confirmation du retrait du groupe
//ConfirmLeave,
/// Afficher plus de groupes
More,
/// Afficher ou cacher la fenetre pour creer des groupes
ToggleCreate,
/// Afficher ou cacher la fenetre pour rejoindre des groupes
ToggleJoin,
/// Ferme les fenetres modals
CloseModal,
/// Lorsque l'utilisateur clique sur un groupe, on l'enregistre au vu de
/// son ajout futur
SelectGroup(usize),
/// Update the name for the new group
OnChangeName(String),
/// Sélection du nouveau groupe faite, envoie d'un requete en back
SendJoin,
/// Envoie de la requete pour la création de groupe
SendCreate,
/// Requete en back finie
Finish(TypeFinish),
/// Popup d'informations
Info(String, String),
/// Popup d'erreur
Error(String, String),
}
/// Type de retour du back
#[derive(Eq, PartialEq)]
enum TypeFinish {
Join,
Create,
}
impl ListGroups {
/// Appelé lorsque le champs `name` est changé.
fn on_change_name(&mut self, name: String) {
self.new_name = name;
}
/// Appelé lorsque le champs `name` est changé.
fn on_change_game(&mut self, game: String) {
}
/// Check si le groupe est vide ou pas. Si oui, en créer un avec l'utilisateur actuel en
/// capitaine.
fn check_group(&mut self) {
if self.new_group.is_none() {
let mut group = Group::default();
let user: Result<User, StorageError> = LocalStorage::get("auth");
if let Ok(user) = user {
group.captain = user.id;
}
self.new_group = Some(group);
}
}
fn update_group(&mut self) {
if let Some(group) = &mut self.new_group {
group.name = self.new_name.clone();
//group.game = Groups::;
}
}
}
impl Component for ListGroups {
type Message = MsgListGroups;
type Properties = PropGroups;
fn create(ctx: &Context<Self>) -> Self {
Self {
id_user: ctx.props().id.clone(),
..Default::default()
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
if self.groups.len() == 0 {
let id = self.id_user.clone();
ctx.link().send_future(async move {
match Request::get(&format!("/api/users/{}/groups", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
let json: Result<Vec<Group>, Error> = resp.json().await;
match json {
Ok(mut json) => {
for item in json.iter_mut() {
item.get_game_name().await;
}
return MsgListGroups::Done(json);
}
Err(err) => {
log::info!("{}", err.to_string());
()
}
}
}
}
Err(_) => (),
};
MsgListGroups::Info(String::from("Ok"), String::new())
});
}
if self.free_groups.len() == 0 {
let id = self.id_user.clone();
ctx.link().send_future(async move {
match Request::get(&format!("/api/users/{}/not/groups", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
let json: Result<Vec<Group>, Error> = resp.json().await;
match json {
Ok(mut json) => {
for item in json.iter_mut() {
item.get_game_name().await;
}
return MsgListGroups::DoneFree(json);
}
Err(err) => {
log::info!("{}", err.to_string());
()
}
}
}
}
Err(_) => (),
};
MsgListGroups::Info(String::from("Ok"), String::new())
});
}
let more = ctx.link().callback(|_| MsgListGroups::More);
let join = ctx.link().callback(|_| MsgListGroups::ToggleJoin);
let create = ctx.link().callback(|_| MsgListGroups::ToggleCreate);
let close_modal = ctx.link().callback(|_| MsgListGroups::CloseModal);
let finish_join = ctx.link().callback(|_| MsgListGroups::SendJoin);
let change_name = ctx.link().callback(|name: String| MsgListGroups::OnChangeName(name));
let groups: Vec<Html> = self.groups[..self.nb_show].iter().enumerate().map(|(id, group)| {
html!{
<Card>
<h1>{ group.name.clone() }</h1>
<h2>{ group.game.clone() }</h2>
if self.id_user == group.captain {
<Label
color={Color::Blue}
label={ "Capitaine" }
/>
}
<Button
disabled={self.id_user == group.captain}
onclick={ ctx.link().callback(move |_| MsgListGroups::Leave(id)) }variant={Variant::DangerSecondary}
>
{ "Quitter" }
</Button>
</Card>
}}).collect::<Vec<Html>>();
let mut groups_final: Vec<Html> = Vec::new();
for g in groups.chunks(3) {
groups_final.push(html! { <Flex> { g.to_vec().into_flex_items() } </Flex> });
}
let modal = match self.modal {
ModalGroup::Join => html! {
<Modal onclose={close_modal} variant={ ModalVariant::Medium }>
<br />
<Gallery gutter=true>
{ self.free_groups.iter().enumerate().map(|(id, group)| {
html! {
<Card
onclick={ctx.link().callback(move |_| MsgListGroups::SelectGroup(id))}
selectable=true
selected={self.selected_group == id}
>
{group.name.clone()}
</Card>
}
}).collect::<Vec<Html>>() }
</Gallery>
<Button variant={Variant::Primary} onclick={finish_join}>{ "Valider" }</Button>
</Modal>
},
ModalGroup::Create => html! {},
ModalGroup::None => html! {},
};
html! {
<>
<ToastViewer />
<Title>{ "Vos groupes" }</Title>
<Button disabled=true onclick={create} variant={Variant::Control} icon={Some(Icon::PlusCircleIcon)}>{ "Créer un groupe" }</Button>
<Button onclick={join} icon={Some(Icon::PlusCircleIcon)}>{ "Rejoindre un groupe" }</Button>
{ modal }
if self.groups.len() > 0 {
{
html!{
<div>
<Flex modifiers={[FlexModifier::Column.all()]}>
{ groups_final.into_flex_items() }
</Flex>
if self.nb_show < self.groups.len() {
<Button variant={Variant::Primary} onclick={more}>{ "Plus de groupes" }</Button>
}
</div>
}
}
} else {
<p>{ "Vous n'êtes dans aucun groupe." }</p>
}
</>
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
MsgListGroups::Info(title, body) => {
if let Some(parent) = ctx.link().get_parent() {
(parent.clone())
.downcast::<Home>()
.send_message(TestMessage::Toast(ToastType::Info(ToastFields {
title,
body,
})))
}
false
}
MsgListGroups::Error(title, body) => {
if let Some(parent) = ctx.link().get_parent() {
(parent.clone())
.downcast::<Home>()
.send_message(TestMessage::Toast(ToastType::Error(ToastFields {
title,
body,
})))
}
false
}
MsgListGroups::Done(groups) => {
let len = groups.len();
self.groups = groups;
self.nb_show = if len < 3 { len } else { 3 };
true
}
MsgListGroups::DoneFree(groups) => {
self.free_groups = groups;
true
}
MsgListGroups::ToggleJoin => {
let modal = &self.modal;
match modal {
ModalGroup::Join => self.modal = ModalGroup::None,
ModalGroup::None => self.modal = ModalGroup::Join,
ModalGroup::Create => self.modal = ModalGroup::Join,
}
true
}
MsgListGroups::ToggleCreate => {
let modal = &self.modal;
match modal {
ModalGroup::Create => self.modal = ModalGroup::None,
ModalGroup::None => self.modal = ModalGroup::Create,
ModalGroup::Join => self.modal = ModalGroup::Create,
}
true
}
MsgListGroups::CloseModal => {
self.modal = ModalGroup::None;
true
}
MsgListGroups::SendJoin => {
if let Some(group) = self.free_groups.get(self.selected_group) {
let id = group.id.clone();
ctx.link().send_future(async move {
match Request::put(&format!("/api/groups/{}/join", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
MsgListGroups::Finish(TypeFinish::Join)
} else {
MsgListGroups::Error(
String::from("Erreur"),
String::from("Pas de réponse 200"),
)
}
}
Err(_) => {
MsgListGroups::Error(String::from("Erreur"), String::from("Bruh"))
}
}
});
} else {
ctx.link().send_message(MsgListGroups::Error(
String::from("Erreur"),
String::from("Contactez nous si vous êtes tombés sur cette erreur."),
));
}
false
}
MsgListGroups::SendCreate => {
return false;
if let Some(group) = self.free_groups.get(self.selected_group) {
let id = group.id.clone();
ctx.link().send_future(async move {
match Request::put(&format!("/api/groups/{}/create", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
MsgListGroups::Finish(TypeFinish::Join)
} else {
MsgListGroups::Error(
String::from("Erreur"),
String::from("Pas de réponse 200"),
)
}
}
Err(_) => {
MsgListGroups::Error(String::from("Erreur"), String::from("Bruh"))
}
}
});
} else {
ctx.link().send_message(MsgListGroups::Error(
String::from("Erreur"),
String::from("Contactez nous si vous êtes tombés sur cette erreur."),
));
}
false
}
MsgListGroups::Finish(t) => match t {
TypeFinish::Join => {
self.groups
.push(self.free_groups.remove(self.selected_group));
if self.nb_show < 3 {
self.nb_show += 1;
}
true
}
TypeFinish::Create => false,
}
MsgListGroups::FinishLeave(id) => {
let group = self.groups.remove(id);
let name = group.name.clone();
self.free_groups.push(group);
if self.nb_show > 0 && id <= self.nb_show {
self.nb_show -= 1;
}
ctx.link().send_message(MsgListGroups::Info(
String::from(&format!("Vous avez bien quitté le groupe {}", name)),
String::new(),
));
true
}
MsgListGroups::SelectGroup(id) => {
self.selected_group = id;
true
}
MsgListGroups::Leave(id_group) => {
if let Some(group) = self.groups.get(id_group) {
let id = group.id.clone();
ctx.link().send_future(async move {
match Request::put(&format!("/api/groups/{}/leave", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
MsgListGroups::FinishLeave(id_group)
} else {
MsgListGroups::Error(
String::from("Erreur"),
String::from("Pas de réponse 200"),
)
}
}
Err(_) => {
MsgListGroups::Error(String::from("Erreur"), String::from("Bruh"))
}
}
});
} else {
ctx.link().send_message(MsgListGroups::Error(
String::from("Erreur"),
String::from("Contactez nous si vous êtes tombés sur cette erreur."),
));
}
false
}
MsgListGroups::Refresh => true,
MsgListGroups::OnChangeName(name) => {
self.on_change_name(name);
true
}
MsgListGroups::More => {
self.nb_show += 3;
if self.nb_show > self.groups.len() {
self.nb_show -= self.nb_show - self.groups.len();
}
true
}
}
}
}