use dioxus::prelude::*;
use dioxus_provider::prelude::*;
use std::{
sync::atomic::{AtomicU32, Ordering},
time::Duration,
};
#[cfg(not(target_family = "wasm"))]
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(target_family = "wasm")]
use web_time::{SystemTime, UNIX_EPOCH};
#[cfg(not(target_family = "wasm"))]
use tokio::time::sleep;
#[cfg(target_family = "wasm")]
use wasmtimer::tokio::sleep;
static API_CALL_COUNTER: AtomicU32 = AtomicU32::new(0);
#[provider(interval = "2s", cache_expiration = "10s")]
async fn fetch_live_stats() -> Result<LiveStats, String> {
println!("🔄 [FETCH] Live stats fetch started");
sleep(Duration::from_millis(300)).await;
let call_number = API_CALL_COUNTER.fetch_add(1, Ordering::SeqCst) + 1;
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
Ok(LiveStats {
active_users: (call_number * 13) % 1000 + 100,
cpu_usage: (call_number * 7) % 100,
memory_usage: (call_number * 11) % 80 + 20,
last_updated: timestamp,
fetch_count: call_number,
})
}
#[provider(interval = "5s", cache_expiration = "20s")]
async fn fetch_system_metrics() -> Result<SystemMetrics, String> {
println!("🔄 [FETCH] System metrics fetch started");
sleep(Duration::from_millis(800)).await;
let call_number = API_CALL_COUNTER.fetch_add(1, Ordering::SeqCst) + 1;
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
Ok(SystemMetrics {
disk_usage: (call_number * 3) % 90 + 10,
network_io: format!("{:.1} MB/s", (call_number as f64 * 1.7) % 50.0),
uptime_hours: call_number * 2,
last_updated: timestamp,
fetch_count: call_number,
})
}
#[provider(interval = "10s", cache_expiration = "30s")]
async fn fetch_business_metrics() -> Result<BusinessMetrics, String> {
println!("🔄 [FETCH] Business metrics fetch started");
sleep(Duration::from_millis(1200)).await;
let call_number = API_CALL_COUNTER.fetch_add(1, Ordering::SeqCst) + 1;
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
Ok(BusinessMetrics {
daily_revenue: (call_number * 127) % 10000 + 5000,
active_subscriptions: (call_number * 89) % 500 + 200,
conversion_rate: format!("{:.2}%", (call_number as f64 * 0.3) % 15.0 + 2.0),
last_updated: timestamp,
fetch_count: call_number,
})
}
#[derive(Clone, PartialEq, Debug)]
pub struct LiveStats {
active_users: u32,
cpu_usage: u32,
memory_usage: u32,
last_updated: u64,
fetch_count: u32,
}
#[derive(Clone, PartialEq, Debug)]
pub struct SystemMetrics {
disk_usage: u32,
network_io: String,
uptime_hours: u32,
last_updated: u64,
fetch_count: u32,
}
#[derive(Clone, PartialEq, Debug)]
pub struct BusinessMetrics {
daily_revenue: u32,
active_subscriptions: u32,
conversion_rate: String,
last_updated: u64,
fetch_count: u32,
}
fn main() {
let _ = dioxus_provider::init();
println!("🚀 Starting Interval Refresh Demo");
println!("⏰ Demonstrating automatic background data refresh at configurable intervals");
launch(App);
}
#[component]
fn App() -> Element {
rsx! {
div { class: "container",
style { {include_str!("./assets/style.css")} }
div { class: "header",
h1 { class: "main-title", "⏱️ Interval Refresh Demo" }
p { class: "subtitle", "Automatic Background Data Updates" }
}
div { class: "dashboard",
LiveStatsCard { }
SystemMetricsCard { }
BusinessMetricsCard { }
}
div { class: "info",
h3 { "⚡ Automatic Updates" }
p { "All data refreshes automatically in the background without any user interaction!" }
ul {
li { "🟢 Live Stats: Updates every 2 seconds" }
li { "🔵 System Metrics: Updates every 5 seconds" }
li { "🟣 Business Metrics: Updates every 10 seconds" }
}
p { class: "note",
"💡 Watch the fetch count and timestamps to see automatic updates in action!"
}
}
}
}
}
#[component]
fn LiveStatsCard() -> Element {
let data = use_provider(fetch_live_stats(), ());
rsx! {
MetricsCard {
title: "Live Stats (2s interval)".to_string(),
description: "High-frequency metrics that update every 2 seconds".to_string(),
data: data,
color_class: "live".to_string(),
}
}
}
#[component]
fn SystemMetricsCard() -> Element {
let data = use_provider(fetch_system_metrics(), ());
rsx! {
div { class: "metrics-card system",
div { class: "card-header",
h3 { "System Metrics (5s interval)" }
div { class: match &*data.read() {
State::Loading { .. } => "status loading",
State::Error(_) => "status error",
State::Success(_) => "status success",
}}
}
p { class: "description", "Medium-frequency system monitoring every 5 seconds" }
div { class: "card-content",
match &*data.read() {
State::Loading { .. } => rsx! {
div { class: "loading-state",
div { class: "spinner" }
span { "Loading..." }
}
},
State::Error(e) => rsx! {
div { class: "error-state",
span { "❌ Error: {e}" }
}
},
State::Success(metrics) => rsx! {
div { class: "data-grid",
div { class: "metric",
span { class: "label", "Disk Usage:" }
span { class: "value", "{metrics.disk_usage}%" }
}
div { class: "metric",
span { class: "label", "Network I/O:" }
span { class: "value", "{metrics.network_io}" }
}
div { class: "metric",
span { class: "label", "Uptime:" }
span { class: "value", "{metrics.uptime_hours}h" }
}
div { class: "metric",
span { class: "label", "Fetch Count:" }
span { class: "value fetch-count", "#{metrics.fetch_count}" }
}
div { class: "metric timestamp",
span { class: "label", "Last Updated:" }
span { class: "value", "{metrics.last_updated}" }
}
}
}
}
}
}
}
}
#[component]
fn BusinessMetricsCard() -> Element {
let data = use_provider(fetch_business_metrics(), ());
rsx! {
div { class: "metrics-card business",
div { class: "card-header",
h3 { "Business Metrics (10s interval)" }
div { class: match &*data.read() {
State::Loading { .. } => "status loading",
State::Error(_) => "status error",
State::Success(_) => "status success",
}}
}
p { class: "description", "Low-frequency business data every 10 seconds" }
div { class: "card-content",
match &*data.read() {
State::Loading { .. } => rsx! {
div { class: "loading-state",
div { class: "spinner" }
span { "Loading..." }
}
},
State::Error(e) => rsx! {
div { class: "error-state",
span { "❌ Error: {e}" }
}
},
State::Success(metrics) => rsx! {
div { class: "data-grid",
div { class: "metric",
span { class: "label", "Daily Revenue:" }
span { class: "value", "${metrics.daily_revenue}" }
}
div { class: "metric",
span { class: "label", "Subscriptions:" }
span { class: "value", "{metrics.active_subscriptions}" }
}
div { class: "metric",
span { class: "label", "Conversion:" }
span { class: "value", "{metrics.conversion_rate}" }
}
div { class: "metric",
span { class: "label", "Fetch Count:" }
span { class: "value fetch-count", "#{metrics.fetch_count}" }
}
div { class: "metric timestamp",
span { class: "label", "Last Updated:" }
span { class: "value", "{metrics.last_updated}" }
}
}
}
}
}
}
}
}
#[component]
fn MetricsCard(
title: String,
description: String,
data: Signal<State<LiveStats, String>>,
color_class: String,
) -> Element {
let status_class = match &*data.read() {
State::Loading { .. } => "status loading",
State::Error(_) => "status error",
State::Success(_) => "status success",
};
rsx! {
div { class: "metrics-card {color_class}",
div { class: "card-header",
h3 { "{title}" }
div { class: "{status_class}" }
}
p { class: "description", "{description}" }
div { class: "card-content",
match &*data.read() {
State::Loading { .. } => rsx! {
div { class: "loading-state",
div { class: "spinner" }
span { "Loading..." }
}
},
State::Error(e) => rsx! {
div { class: "error-state",
span { "❌ Error: {e}" }
}
},
State::Success(stats) => rsx! {
div { class: "data-grid",
div { class: "metric",
span { class: "label", "Active Users:" }
span { class: "value", "{stats.active_users}" }
}
div { class: "metric",
span { class: "label", "CPU Usage:" }
span { class: "value", "{stats.cpu_usage}%" }
}
div { class: "metric",
span { class: "label", "Memory:" }
span { class: "value", "{stats.memory_usage}%" }
}
div { class: "metric",
span { class: "label", "Fetch Count:" }
span { class: "value fetch-count", "#{stats.fetch_count}" }
}
div { class: "metric timestamp",
span { class: "label", "Last Updated:" }
span { class: "value", "{stats.last_updated}" }
}
}
}
}
}
}
}
}