Skip to main content

ui/
toast.rs

1use std::time::Duration;
2
3use api::dto::AvailableGameEventDTO;
4use dioxus::prelude::*;
5use dioxus_primitives::toast::{ToastOptions, ToastType, consume_toast};
6
7/// Helper for displaying toast notifications within the UI.
8///
9/// This utility provides a consistent interface for raising user-facing
10/// toast messages through the application's toast API. It centralizes
11/// formatting, duration choices, and toast types so that components can
12/// emit notifications without duplicating boilerplate.
13///
14/// All methods delegate to a private wrapper around
15/// [`consume_toast()`], which retrieves the active toast handle and
16/// displays the configured toast.
17pub struct Toast;
18
19impl Toast {
20    fn toast(
21        title: &str,
22        description: &str,
23        toast_type: ToastType,
24        duration: Duration,
25        permanent: bool,
26    ) {
27        let api = consume_toast();
28        api.show(
29            String::from(title),
30            toast_type,
31            ToastOptions::new()
32                .description(description)
33                .duration(duration)
34                .permanent(permanent),
35        );
36    }
37
38    /// Displays an error toast corresponding to a failed user command.
39    ///
40    /// This is intended for surfacing errors triggered by client-side
41    /// actions (button clicks, form submissions, etc.) and logs the error
42    /// via `warn!` before showing a toast.
43    ///
44    /// The toast is non-permanent and remains visible for 30 seconds.
45    pub fn command_error(command: &str, error: String) {
46        warn!("{error}");
47        Self::toast(
48            command,
49            &error,
50            ToastType::Error,
51            Duration::from_secs(30),
52            false,
53        );
54    }
55
56    /// Displays a notification in response to a change in game availability.
57    ///
58    /// This is typically called when the application receives an
59    /// [`AvailableGameEventDTO`] from the server. The toast indicates
60    /// whether a game was created or removed.
61    ///
62    /// The toast is informational and expires after 10 seconds.
63    pub fn available_game(event: AvailableGameEventDTO) {
64        let description = match event {
65            AvailableGameEventDTO::Created { name, .. } => format!("Created {name}"),
66        };
67
68        Self::toast(
69            "Available game",
70            &description,
71            ToastType::Info,
72            Duration::from_secs(10),
73            false,
74        );
75    }
76
77    /// Displays a notification of scoring.
78    ///
79    /// The toast is informational and expires after 10 seconds.
80    pub fn score(title: &str, description: &str) {
81        Self::toast(
82            title,
83            description,
84            ToastType::Info,
85            Duration::from_secs(5),
86            false,
87        )
88    }
89
90    /// Displays a server-side error notification.
91    ///
92    /// Intended for situations where a backend service returns an error
93    /// or cannot be reached. These are treated as higher-severity issues
94    /// and are shown as warning toasts with a longer, permanent duration.
95    pub fn server_error(service: &str, error: String) {
96        Self::toast(
97            service,
98            &error,
99            ToastType::Warning,
100            Duration::from_secs(30),
101            true,
102        );
103    }
104}