use std::ops::Range; use serde::{Deserialize, Serialize}; use yew::prelude::*; use yew_router::components::Link; use crate::Route; const ELLIPSIS: &str = "\u{02026}"; #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] pub struct PageQuery { pub page: u8, } #[derive(Clone, Debug, PartialEq, Eq, Properties)] pub struct PropsNavigation { pub page: u8, pub total_pages: u8, pub route_to_page: Route, } #[function_component] pub fn RelNavButtons(props: &PropsNavigation) -> Html { let PropsNavigation { page, total_pages, route_to_page: to, } = props.clone(); html! { <> classes={classes!("pagination-previous")} disabled={page==1} query={Some(PageQuery{page: page - 1})} to={to.clone()} > { "Previous" } > classes={classes!("pagination-next")} disabled={page==total_pages} query={Some(PageQuery{page: page + 1})} {to} > { "Next page" } > } } #[derive(Properties, Clone, Debug, PartialEq, Eq)] pub struct RenderLinksProps { range: Range, len: usize, max_links: usize, props: PropsNavigation, } #[function_component] pub fn RenderLinks(props: &RenderLinksProps) -> Html { let RenderLinksProps { range, len, max_links, props, } = props.clone(); let mut range = range; if len > max_links { let last_link = html! {}; let links = range .take(max_links - 2) .map(|page| html! {}); html! { <> { for links }
  • { ELLIPSIS }
  • { last_link } } } else { html! { for page in range { } } } } #[derive(Properties, Clone, Debug, PartialEq, Eq)] pub struct RenderLinkProps { to_page: u8, props: PropsNavigation, } #[function_component] pub fn RenderLink(props: &RenderLinkProps) -> Html { let RenderLinkProps { to_page, props } = props.clone(); let PropsNavigation { page, route_to_page, .. } = props; let is_current_class = if to_page == page { "is-current" } else { "" }; html! {
  • classes={classes!("pagination-link", is_current_class)} to={route_to_page} query={Some(PageQuery{page: to_page})} > { to_page } >
  • } } #[function_component] pub fn Links(props: &PropsNavigation) -> Html { const LINKS_PER_SIDE: usize = 3; let PropsNavigation { page, total_pages, .. } = *props; let pages_prev = page.checked_sub(1).unwrap_or_default() as usize; let pages_next = (total_pages - page) as usize; let links_left = LINKS_PER_SIDE.min(pages_prev) // if there are less than `LINKS_PER_SIDE` to the right, we add some more on the left. + LINKS_PER_SIDE.checked_sub(pages_next).unwrap_or_default(); let links_right = 2 * LINKS_PER_SIDE - links_left; html! { <> } } #[function_component] pub fn Pagination(props: &PropsNavigation) -> Html { html! { } } #[function_component] pub fn Nav() -> Html { let navbar_active = use_state_eq(|| false); let toggle_navbar = { let navbar_active = navbar_active.clone(); Callback::from(move |_| { navbar_active.set(!*navbar_active); }) }; let active_class = if !*navbar_active { "is-active" } else { "" }; html! { } }