use dioxus::prelude::*;
use web_sys::UrlSearchParams;
use web_sys::wasm_bindgen::JsValue;
use crate::dioxus::body::TableBody;
use crate::dioxus::controls::PaginationControls;
use crate::dioxus::header::TableHeader;
use crate::dioxus::types::SortOrder;
use crate::dioxus::types::TableProps;
#[component]
pub fn Table(props: TableProps) -> Element {
let TableProps {
data,
columns,
page_size,
loading,
paginate,
search,
texts,
classes,
} = props;
let mut page = use_signal(|| 0_usize);
let mut sort_column = use_signal(|| None::<&'static str>);
let mut sort_order = use_signal(SortOrder::default);
let mut search_query = use_signal(String::new);
#[cfg(target_family = "wasm")]
use_effect(move || {
let window = web_sys::window().unwrap();
let location = window.location();
let search = location.search().unwrap_or_default();
let params = UrlSearchParams::new_with_str(&search).unwrap();
if let Some(search_val) = params.get("search") {
search_query.set(search_val);
}
});
#[cfg(target_family = "wasm")]
let update_search_param = move |query: &str| {
let window = web_sys::window().unwrap();
let href = window.location().href().unwrap();
let url = web_sys::Url::new(&href).unwrap();
let params = url.search_params();
params.set("search", query);
url.set_search(¶ms.to_string().as_string().unwrap_or_default());
window
.history()
.unwrap()
.replace_state_with_url(&JsValue::NULL, "", Some(&url.href()))
.unwrap();
};
let filtered_rows = {
let mut rows = data.clone();
if !search_query().is_empty() {
rows.retain(|row| {
columns.iter().any(|col| {
row.get(col.id)
.map(|v| v.to_lowercase().contains(&search_query().to_lowercase()))
.unwrap_or(false)
})
});
}
if let Some(col_id) = sort_column() {
if let Some(col) = columns.iter().find(|c| c.id == col_id) {
rows.sort_by(|a, b| {
let val = "".to_string();
let a_val = a.get(col.id).unwrap_or(&val);
let b_val = b.get(col.id).unwrap_or(&val);
match sort_order() {
SortOrder::Asc => a_val.cmp(b_val),
SortOrder::Desc => b_val.cmp(a_val),
}
});
}
}
rows
};
let total_pages = (filtered_rows.len() as f64 / page_size as f64).ceil() as usize;
let start = page() * page_size;
let end = ((page() + 1) * page_size).min(filtered_rows.len());
let page_rows = &filtered_rows[start..end];
let on_sort_column = move |id: &'static str| {
if Some(id) == sort_column() {
sort_order.set(match sort_order() {
SortOrder::Asc => SortOrder::Desc,
SortOrder::Desc => SortOrder::Asc,
});
} else {
sort_column.set(Some(id));
sort_order.set(SortOrder::Asc);
}
};
let pagination_controls = if paginate {
rsx! {
PaginationControls {
page: page,
total_pages: total_pages,
classes: classes.clone(),
texts: texts.clone(),
}
}
} else {
rsx! {}
};
rsx! {
div {
class: "{classes.container}",
if search {
input {
class: "{classes.search_input}",
r#type: "text",
value: "{search_query()}",
placeholder: "{texts.search_placeholder}",
oninput: move |e| {
let val = e.value();
search_query.set(val.clone());
page.set(0);
#[cfg(target_family = "wasm")]
update_search_param(&val);
}
}
}
table {
class: "{classes.table}",
TableHeader {
columns: columns.clone(),
sort_column: sort_column,
sort_order: sort_order,
on_sort_column: on_sort_column,
classes: classes.clone(),
}
TableBody {
columns: columns.clone(),
rows: page_rows.to_vec(),
loading: loading,
classes: classes.clone(),
texts: texts.clone(),
}
}
{pagination_controls}
}
}
}