Skip to main content

api/services/queries/
get_available_games.rs

1use chrono::{DateTime, Utc};
2#[cfg(feature = "server")]
3use dioxus::fullstack::extract::State;
4use dioxus::prelude::*;
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "server")]
8use crate::ServerStateExtractor;
9use crate::dto::{AvailableGameDTO, UserIdDTO};
10
11/// Optional timestamp used for fetching only records created after a certain point in time.
12///
13/// This is used for pagination or incremental updates.
14/// If `None`, the endpoint returns results from the beginning (or all available games).
15pub type Since = Option<DateTime<Utc>>;
16
17/// Response type for the `get_available_games` API endpoint.
18///
19/// Contains the list of available games for a user, along with pagination information.
20#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
21pub struct AvailableGamesResponse {
22    games: Vec<AvailableGameDTO>,
23    has_more: bool,
24    since: Since,
25}
26
27impl AvailableGamesResponse {
28    /// Returns a slice of available games in this response.
29    pub fn games(&self) -> &[AvailableGameDTO] {
30        &self.games
31    }
32
33    /// Returns `true` if there are more available games beyond this response.
34    pub fn has_more(&self) -> bool {
35        self.has_more
36    }
37
38    /// Returns the `since` timestamp used for pagination, if any.
39    pub fn since(&self) -> &Since {
40        &self.since
41    }
42}
43
44/// Retrieves a list of available games for a given user.
45///
46/// # Parameters
47/// - `user_id`: The ID of the user requesting available games.
48/// - `filter`: Optional string to filter games by name or criteria.
49/// - `since`: Optional timestamp; only games created after this time are returned.
50///
51/// # Returns
52/// On success, returns an [`AvailableGamesResponse`] containing:
53/// - The list of available games (`games`) matching the filter and since parameters.
54/// - Whether there are more games (`has_more`) beyond this response.
55/// - The timestamp used for this query (`since`).
56///
57/// # Errors
58/// Returns a [`ServerError`] if there is an issue fetching games from the server.
59#[get("/api/{user_id}/available_games?filter&since", State(server_state): State<ServerStateExtractor>)]
60pub async fn get_available_games(
61    user_id: UserIdDTO,
62    filter: Option<String>,
63    since: Since,
64) -> Result<AvailableGamesResponse> {
65    use server::{
66        domain::{Availability, UserId},
67        queries::get_available_games,
68    };
69
70    use crate::dto::{AvailabilityDTO, GameIdDTO};
71
72    let user_id = UserId::from(user_id.value());
73    let filter = filter.unwrap_or_default();
74
75    let (games, has_more, since) =
76        get_available_games(server_state.0, user_id, filter, since).await?;
77
78    let games = games
79        .into_iter()
80        .map(|game| {
81            let game_id = GameIdDTO::from(game.id().value());
82            let name = String::from(game.name());
83            let availability = match game.availability() {
84                Availability::Private => AvailabilityDTO::Private,
85                Availability::Public => AvailabilityDTO::Public,
86            };
87            AvailableGameDTO {
88                game_id,
89                name,
90                availability,
91            }
92        })
93        .collect::<Vec<_>>();
94
95    let response = AvailableGamesResponse {
96        games,
97        has_more,
98        since,
99    };
100
101    Ok(response)
102}