lan-party-backend/web/src/state.rs

141 lines
3.8 KiB
Rust

use anyhow::{anyhow, Result};
use async_trait::async_trait;
use lan_party_core::{
event::{Event, EventSpec, EventUpdate},
state::{Events, Users},
user::User,
};
use reqwasm::http::Method;
use sycamore::prelude::*;
use crate::util::api_request;
#[async_trait(?Send)]
pub trait UsersExt {
async fn load(&self) -> Result<()>;
async fn delete(&self, name: &str) -> Result<()>;
async fn update_score(&self, name: &str, score: i64) -> Result<()>;
async fn add(&self, name: &str) -> Result<()>;
}
#[async_trait(?Send)]
impl UsersExt for Users {
async fn load(&self) -> Result<()> {
self.0.set(
api_request::<_, Vec<User>>(
Method::GET,
"/user?sort=score&order=desc",
Option::<()>::None,
)
.await
.and_then(|inner| inner.ok_or(anyhow!("missing body")))?,
);
Ok(())
}
async fn delete(&self, name: &str) -> Result<()> {
let users_ref = self.0.get();
let user: &User = users_ref.iter().find(|user| user.name == name).unwrap();
api_request::<_, ()>(
Method::DELETE,
&format!("/user/{}", user.name),
Option::<()>::None,
)
.await?;
let cloned = (*users_ref)
.clone()
.iter()
.cloned()
.filter(|u| u.name != user.name)
.collect();
self.0.set(cloned);
Ok(())
}
async fn update_score(&self, name: &str, score: i64) -> Result<()> {
let users_ref = self.0.get();
let user: &User = users_ref.iter().find(|user| &user.name == name).unwrap();
api_request::<_, ()>(
Method::POST,
&format!("/user/{}/score", user.name),
Some(score),
)
.await?;
let cloned = (*users_ref).clone();
let new_users: Vec<_> = cloned
.into_iter()
.map(|mut user| {
if &user.name == name {
user.score = score
}
user
})
.collect();
self.0.set(new_users);
Ok(())
}
async fn add(&self, name: &str) -> Result<()> {
let user = api_request::<&str, User>(Method::POST, "/user", Some(name)).await?;
self.0.modify().push(user.ok_or(anyhow!("missing body"))?);
Ok(())
}
}
#[async_trait(?Send)]
pub trait EventsExt {
async fn load(&self) -> Result<()>;
async fn add(&self, event_spec: EventSpec) -> Result<()>;
async fn update_event(&self, event_name: &str, event_update: EventUpdate) -> Result<()>;
async fn delete(&self, event_name: &str) -> Result<()>;
}
#[async_trait(?Send)]
impl EventsExt for Events {
async fn load(&self) -> Result<()> {
self.0.set(
api_request::<_, Vec<Event>>(Method::GET, "/event?concluded=false", Option::<()>::None)
.await
.and_then(|inner| inner.ok_or(anyhow!("missing body")))?,
);
Ok(())
}
async fn add(&self, event_spec: EventSpec) -> Result<()> {
let new_event =
api_request::<EventSpec, Event>(Method::POST, "/event", Some(event_spec)).await?;
self.0
.modify()
.push(new_event.ok_or(anyhow!("missing body"))?);
Ok(())
}
async fn update_event(&self, event_name: &str, event_update: EventUpdate) -> Result<()> {
api_request::<EventUpdate, ()>(
Method::POST,
&format!("/event/{}", event_name),
Some(event_update),
)
.await?;
self.load().await?;
Ok(())
}
async fn delete(&self, event_name: &str) -> Result<()> {
api_request::<(), ()>(Method::DELETE, &format!("/event/{}", event_name), None).await?;
self.load().await?;
Ok(())
}
}