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}