Rewrite to chatty but functional API.

This commit is contained in:
2025-06-14 22:16:13 +02:00
parent d1832bc794
commit db6f55bc47
20 changed files with 423 additions and 175 deletions

View File

@@ -1,27 +1,20 @@
use std::fmt::Display;
use chrono::{DateTime, Local};
use gamenight_api_client_rs::models;
use uuid::Uuid;
#[derive(Clone)]
pub struct Gamenight {
pub id: Uuid,
pub name: String,
pub start_time: DateTime<Local>
pub start_time: DateTime<Local>,
pub owner_id: Uuid,
}
impl From<models::Gamenight> for Gamenight {
fn from(value: models::Gamenight) -> Self {
Self {
name: value.name,
start_time: DateTime::parse_from_rfc3339(&value.datetime).unwrap().into()
}
}
}
impl Display for Gamenight {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, r#"
write!(f, r#"
Name: {}
When: {}
"#, self.name, self.start_time.format("%d-%m-%Y %H:%M"))
When: {}"#, self.name, self.start_time.format("%d-%m-%Y %H:%M"))
}
}

View File

@@ -1 +1,2 @@
pub mod gamenight;
pub mod gamenight;
pub mod user;

View File

@@ -0,0 +1,7 @@
use uuid::Uuid;
#[derive(Clone)]
pub struct User {
pub id: Uuid,
pub username: String
}

View File

@@ -0,0 +1,34 @@
use std::fmt::Display;
use async_trait::async_trait;
use gamenight_api_client_rs::{apis::default_api::join_post, models::GamenightId};
use uuid::Uuid;
use super::{Flow, FlowOutcome, FlowResult, GamenightState};
#[derive(Clone)]
pub struct Join {
gamenight_id: Uuid
}
impl Join {
pub fn new(gamenight_id: Uuid) -> Self {
Self {
gamenight_id
}
}
}
#[async_trait]
impl<'a> Flow<'a> for Join {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let _ = join_post(&state.configuration, Some(GamenightId{gamenight_id: self.gamenight_id.to_string()})).await?;
Ok((FlowOutcome::Successful, state))
}
}
impl Display for Join {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Join")
}
}

View File

@@ -1,8 +1,10 @@
use chrono::DateTime;
use gamenight_api_client_rs::apis::default_api::get_gamenights;
use inquire::Select;
use uuid::Uuid;
use crate::flows::view_gamenight::ViewGamenight;
use crate::{domain::{gamenight::Gamenight}, flows::view_gamenight::ViewGamenight};
use super::{exit::Exit, *};
@@ -22,9 +24,18 @@ impl<'a> Flow<'a> for ListGamenights {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
let response = get_gamenights(&state.configuration).await?;
let mut view_flows = response.into_iter().map(|gamenight| -> Box<dyn Flow<'a> + Send> {
Box::new(ViewGamenight::new(gamenight.into()))
}).collect::<Vec<Box<dyn Flow<'a> + Send>>>();
let mut view_flows: Vec<Box<dyn Flow<'_> + Send>> = vec![];
for response in response.iter() {
let gamenight = Gamenight {
id: Uuid::parse_str(&response.id)?,
name: response.name.clone(),
start_time:DateTime::parse_from_rfc3339(&response.datetime)?.into(),
owner_id: Uuid::parse_str(&response.owner_id)?
};
view_flows.push(Box::new(ViewGamenight::new(gamenight)));
}
view_flows.push(Box::new(Exit::new()));
let choice = Select::new("What gamenight would you like to view?", view_flows)
@@ -38,5 +49,4 @@ impl Display for ListGamenights {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "List all gamenights")
}
}
}

View File

@@ -2,7 +2,7 @@ use std::fmt::Display;
use async_trait::async_trait;
use chrono::ParseError;
use gamenight_api_client_rs::apis::configuration::Configuration;
use gamenight_api_client_rs::apis::{configuration::Configuration, Error};
use inquire::InquireError;
use dyn_clone::DynClone;
@@ -13,6 +13,7 @@ mod exit;
mod list_gamenights;
mod add_gamenight;
mod view_gamenight;
mod join;
pub struct GamenightState {
configuration: Configuration,
@@ -45,16 +46,24 @@ impl From<InquireError> for FlowError {
}
}
impl<T> From<gamenight_api_client_rs::apis::Error<T>> for FlowError {
fn from(value: gamenight_api_client_rs::apis::Error<T>) -> Self {
impl From<ParseError> for FlowError {
fn from(value: ParseError) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<ParseError> for FlowError {
fn from(value: ParseError) -> Self {
impl<T> From<Error<T>> for FlowError {
fn from(value: Error<T>) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<uuid::Error> for FlowError {
fn from(value: uuid::Error) -> Self {
Self {
error: value.to_string()
}

View File

@@ -1,7 +1,9 @@
use gamenight_api_client_rs::{apis::default_api::{participants_get, user_get}, models::{GamenightId, UserId}};
use inquire::Select;
use uuid::Uuid;
use crate::{domain::gamenight::Gamenight, flows::exit::Exit};
use crate::{domain::{gamenight::Gamenight, user::User}, flows::{exit::Exit, join::Join}};
use super::*;
@@ -18,12 +20,30 @@ impl ViewGamenight {
}
}
fn vec_user_to_usernames_string(users: Vec<User>) -> String {
let string_list: Vec<String> = users.iter().map(|x| {x.username.clone()}).collect();
string_list.join(", ")
}
#[async_trait]
impl<'a> Flow<'a> for ViewGamenight {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
print!("{}", self.gamenight);
let participants = participants_get(&state.configuration, Some(GamenightId{gamenight_id: self.gamenight.id.to_string()})).await?;
let mut users = vec![];
for participant in participants.participants.iter() {
let user = user_get(&state.configuration, Some(UserId{user_id: participant.clone()})).await?;
users.push(User {
id: Uuid::parse_str(&user.id)?,
username: user.username
});
}
println!("{}\nwho: {}", self.gamenight, vec_user_to_usernames_string(users));
let options: Vec<Box<dyn Flow<'a> + Send>> = vec![
Box::new(Join::new(self.gamenight.id)),
Box::new(Exit::new())
];
let choice = Select::new("What do you want to do:", options)