use dioxus::prelude::*; use crate::api; use crate::app::{Lang, Route}; use crate::components::plant_card::PlantCard; use crate::i18n::{pick_name, t}; #[component] pub fn Home() -> Element { let lang = use_context::().0; let mut search_query = use_signal(|| String::new()); let species = use_resource(|| async { api::list_species(1, 8, None, None).await }); let stats = use_resource(|| async { api::get_stats().await }); let l = lang.read().clone(); rsx! { div { class: "page home-page", // Hero section div { class: "hero", h1 { class: "hero-title", "HerbAPI" } p { class: "hero-subtitle", "{t(&l, \"subtitle\")}" } } // Stats cards div { class: "stats-row", match &*stats.read() { None => rsx! { for _ in 0..6 { div { class: "stat-card stat-card-loading", span { class: "stat-value", "\u{2014}" } span { class: "stat-label", "\u{2026}" } } } }, Some(Err(_)) => rsx! {}, Some(Ok(s)) => rsx! { StatCard { value: s.families, label: t(&l, "stat.families"), icon: "\u{1fab4}" } StatCard { value: s.species, label: t(&l, "stat.species"), icon: "\u{1f33f}" } StatCard { value: s.cultivars, label: t(&l, "stat.cultivars"), icon: "\u{1f331}" } StatCard { value: s.suppliers, label: t(&l, "stat.suppliers"), icon: "\u{1f6d2}" } StatCard { value: s.companions, label: t(&l, "stat.companions"), icon: "\u{1f91d}" } StatCard { value: s.images, label: t(&l, "stat.images"), icon: "\u{1f5bc}\u{fe0f}" } }, } } // Search bar div { class: "search-bar", input { r#type: "text", placeholder: "{t(&l, \"search.placeholder\")}", value: "{search_query}", oninput: move |e| search_query.set(e.value()), onkeydown: move |e| { if e.key() == Key::Enter { let nav = navigator(); nav.push(Route::SearchPage {}); } }, } } // Quick filters h2 { "{t(&l, \"home.quick_filters\")}" } div { class: "quick-filters", a { href: "/species?nitrogen_fixer=true", class: "quick-filter-btn qf-nitrogen", span { class: "qf-icon", "\u{2699}\u{fe0f}" } span { "{t(&l, \"filter.nitrogen_fixers\")}" } } a { href: "/species?min_nectar=3", class: "quick-filter-btn qf-bee", span { class: "qf-icon", "\u{1f41d}" } span { "{t(&l, \"filter.bee_plants\")}" } } a { href: "/species?plant_layer=ground_cover", class: "quick-filter-btn qf-ground", span { class: "qf-icon", "\u{1f343}" } span { "{t(&l, \"filter.ground_cover\")}" } } a { href: "/species?plant_layer=canopy", class: "quick-filter-btn qf-tree", span { class: "qf-icon", "\u{1f333}" } span { "{t(&l, \"filter.fruit_trees\")}" } } } // Featured species h2 { "{t(&l, \"home.featured_species\")}" } match &*species.read() { None => rsx! { p { "{t(&l, \"loading\")}" } }, Some(Err(e)) => rsx! { p { class: "error", "Error: {e}" } }, Some(Ok(data)) => rsx! { div { class: "card-grid", for s in data.data.iter().take(8) { { let card_common = pick_name(&lang.read(), &s.name_de, &s.name_en, &s.name_scientific); let show_common = if card_common == s.name_scientific { None } else { Some(card_common) }; rsx! { PlantCard { key: "{s.id}", slug: s.slug.clone(), name: s.name_scientific.clone(), name_common: show_common, entity_type: "species".to_string(), } } } } } }, } } } } #[component] fn StatCard(value: i64, label: &'static str, icon: &'static str) -> Element { rsx! { div { class: "stat-card", span { class: "stat-icon", "{icon}" } span { class: "stat-value", "{value}" } span { class: "stat-label", "{label}" } } } }