43 lines
1.2 KiB
Rust
43 lines
1.2 KiB
Rust
|
|
use leptos::prelude::*;
|
||
|
|
|
||
|
|
#[component]
|
||
|
|
pub fn StatCardClient(
|
||
|
|
label: String,
|
||
|
|
value: String,
|
||
|
|
change: Option<String>,
|
||
|
|
trend_positive: bool,
|
||
|
|
icon: Option<Children>,
|
||
|
|
class: &'static str,
|
||
|
|
) -> impl IntoView {
|
||
|
|
let trend_color = if trend_positive {
|
||
|
|
"text-green-400"
|
||
|
|
} else {
|
||
|
|
"text-red-400"
|
||
|
|
};
|
||
|
|
|
||
|
|
view! {
|
||
|
|
<div class={format!("ds-card p-6 {}", class)}>
|
||
|
|
<div class="flex items-start justify-between">
|
||
|
|
<div class="flex-1">
|
||
|
|
<p class="text-sm text-white/60 mb-1">{label}</p>
|
||
|
|
<p class="text-3xl font-bold text-white">{value}</p>
|
||
|
|
{change.map(|ch| {
|
||
|
|
view! {
|
||
|
|
<p class={format!("text-sm mt-2 {}", trend_color)}>
|
||
|
|
{ch}
|
||
|
|
</p>
|
||
|
|
}
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
{icon.map(|icon_fn| {
|
||
|
|
view! {
|
||
|
|
<div class="ml-4">
|
||
|
|
{icon_fn()}
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
}
|