fix(toast): simplify style, remove duplicate backend notifications
This commit is contained in:
@@ -85,24 +85,12 @@ pub async fn add_torrent_handler(
|
||||
tracing::error!("rTorrent returned fault: {}", response);
|
||||
return StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
let _ =
|
||||
state
|
||||
.event_bus
|
||||
.send(shared::AppEvent::Notification(shared::SystemNotification {
|
||||
level: shared::NotificationLevel::Success,
|
||||
message: "Torrent added successfully".to_string(),
|
||||
}));
|
||||
// Note: Frontend shows its own toast, no SSE notification needed
|
||||
StatusCode::OK
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to add torrent: {}", e);
|
||||
let _ =
|
||||
state
|
||||
.event_bus
|
||||
.send(shared::AppEvent::Notification(shared::SystemNotification {
|
||||
level: shared::NotificationLevel::Error,
|
||||
message: format!("Failed to add torrent: {}", e),
|
||||
}));
|
||||
// Note: Frontend shows its own toast, no SSE notification needed
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
}
|
||||
}
|
||||
@@ -136,12 +124,7 @@ pub async fn handle_torrent_action(
|
||||
if payload.action == "delete_with_data" {
|
||||
return match delete_torrent_with_data(&client, &payload.hash).await {
|
||||
Ok(msg) => {
|
||||
let _ = state.event_bus.send(shared::AppEvent::Notification(
|
||||
shared::SystemNotification {
|
||||
level: shared::NotificationLevel::Success,
|
||||
message: format!("Torrent deleted with data: {}", payload.hash),
|
||||
},
|
||||
));
|
||||
// Note: Frontend shows its own toast
|
||||
(StatusCode::OK, msg).into_response()
|
||||
}
|
||||
Err((status, msg)) => (status, msg).into_response(),
|
||||
@@ -159,13 +142,7 @@ pub async fn handle_torrent_action(
|
||||
|
||||
match client.call(method, ¶ms).await {
|
||||
Ok(_) => {
|
||||
let _ =
|
||||
state
|
||||
.event_bus
|
||||
.send(shared::AppEvent::Notification(shared::SystemNotification {
|
||||
level: shared::NotificationLevel::Info,
|
||||
message: format!("Action '{}' executed on torrent", payload.action),
|
||||
}));
|
||||
// Note: Frontend shows its own toast, no SSE notification needed
|
||||
(StatusCode::OK, "Action executed").into_response()
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -2,35 +2,9 @@ use leptos::*;
|
||||
use shared::NotificationLevel;
|
||||
|
||||
// ============================================================================
|
||||
// Toast Icons (Clean Code: Separation of Concerns)
|
||||
// Toast Components - DaisyUI Alert Style
|
||||
// ============================================================================
|
||||
|
||||
/// Returns the appropriate SVG icon for the notification level
|
||||
fn get_toast_icon(level: &NotificationLevel) -> impl IntoView {
|
||||
match level {
|
||||
NotificationLevel::Info => view! {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
}.into_view(),
|
||||
NotificationLevel::Success => view! {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
}.into_view(),
|
||||
NotificationLevel::Warning => view! {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
}.into_view(),
|
||||
NotificationLevel::Error => view! {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
}.into_view(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the DaisyUI alert class for the notification level
|
||||
fn get_alert_class(level: &NotificationLevel) -> &'static str {
|
||||
match level {
|
||||
@@ -41,10 +15,6 @@ fn get_alert_class(level: &NotificationLevel) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Toast Components (Clean Code: Single Responsibility)
|
||||
// ============================================================================
|
||||
|
||||
/// Individual toast item component
|
||||
#[component]
|
||||
fn ToastItem(
|
||||
@@ -53,13 +23,20 @@ fn ToastItem(
|
||||
) -> impl IntoView {
|
||||
let alert_class = get_alert_class(&level);
|
||||
|
||||
let icon = match level {
|
||||
NotificationLevel::Info => "ℹ️",
|
||||
NotificationLevel::Success => "✓",
|
||||
NotificationLevel::Warning => "⚠️",
|
||||
NotificationLevel::Error => "✕",
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class={format!(
|
||||
"alert {} shadow-lg min-w-[280px] max-w-[400px] transition-all duration-300 animate-in slide-in-from-right fade-in",
|
||||
alert_class
|
||||
)}>
|
||||
{get_toast_icon(&level)}
|
||||
<span class="text-sm font-medium truncate">{message}</span>
|
||||
<div
|
||||
class={format!("alert {} shadow-xl", alert_class)}
|
||||
style="min-width: 300px; padding: 12px 16px;"
|
||||
>
|
||||
<span style="font-size: 18px;">{icon}</span>
|
||||
<span style="font-size: 14px; font-weight: 500;">{message}</span>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -71,22 +48,19 @@ pub fn ToastContainer() -> impl IntoView {
|
||||
let notifications = store.notifications;
|
||||
|
||||
view! {
|
||||
// Fixed to viewport with explicit inset values for reliable positioning
|
||||
<div
|
||||
class="fixed flex flex-col gap-2 items-end pointer-events-none"
|
||||
style="bottom: 16px; right: 16px; z-index: 99999;"
|
||||
class="toast toast-end toast-bottom"
|
||||
style="position: fixed; bottom: 20px; right: 20px; z-index: 99999;"
|
||||
>
|
||||
<For
|
||||
each=move || notifications.get()
|
||||
key=|item| item.id
|
||||
children=move |item| {
|
||||
view! {
|
||||
<div class="pointer-events-auto">
|
||||
<ToastItem
|
||||
level=item.notification.level
|
||||
message=item.notification.message
|
||||
/>
|
||||
</div>
|
||||
<ToastItem
|
||||
level=item.notification.level
|
||||
message=item.notification.message
|
||||
/>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user