kayrx-ui 0.1.0

The Kayrx-UI Framework
Documentation
use yew::prelude::*;

pub enum Msg {
    TablePageChange(u32),
    TablePageUp,
    TablePageDown,
}

#[derive(Properties, Clone)]
pub struct Props {
    pub onupdate: Callback<u32>,
    pub total_pages: u32,
    pub current_page: u32,
}

pub struct Pagination {
    link: ComponentLink<Self>,
    onupdate: Callback<u32>,
    total_pages: u32,
    current_page: u32,
}

impl Component for Pagination {
    type Message = Msg;
    type Properties = Props;

    fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
        Pagination {
            link,
            onupdate: props.onupdate,
            total_pages: props.total_pages,
            current_page: props.current_page,
        }
    }

    fn change(&mut self, props: Self::Properties) -> ShouldRender {
        self.total_pages = props.total_pages;
        self.current_page = props.current_page;
        true
    }

    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            Msg::TablePageChange(n) => self.onupdate.emit(n),
            Msg::TablePageUp => {
                if self.current_page < self.total_pages {
                    self.onupdate.emit(self.current_page + 1)
                }
            }
            Msg::TablePageDown => {
                if self.current_page > 1 {
                    self.onupdate.emit(self.current_page - 1)
                }
            }
        }
        true
    }

    fn view(&self) -> Html {
        html! {
            <div class="table-paging">
                <button class="table-paging__btn" onclick=self.link.callback(|_| Msg::TablePageDown)
                    disabled={ self.current_page==1 }>{ "«" }</button>
                { self.view_pagination_button_first() }
                { self.view_pagination_buttons_first() }
                { self.view_pagination_delimiter_first() }
                { self.view_pagination_button_middle() }
                { self.view_pagination_delimiter_last() }
                { self.view_pagination_buttons_last() }
                { self.view_pagination_button_last() }
                <button class="table-paging__btn" onclick=self.link.callback(|_| Msg::TablePageUp)
                    disabled={ self.current_page==self.total_pages }>{ "»" }</button>
            </div>
        }
    }
}

impl Pagination {
    fn view_pagination_button_is_active(&self, page: u32) -> &str {
        let current_page = self.current_page;

        if current_page == page {
            "table-paging__btn--active"
        } else {
            "table-paging__btn"
        }
    }

    fn view_pagination_button(&self, page: u32) -> Html {
        html! {
            <button class={ self.view_pagination_button_is_active(page) }
                onclick=self.link.callback(move |_| Msg::TablePageChange(page))>{ page }</button>
        }
    }

    fn view_pagination_button_first(&self) -> Html {
        self.view_pagination_button(1)
    }

    fn view_pagination_delimiter_first(&self) -> Html {
        let total_pages = self.total_pages;
        let current_page = self.current_page;

        if total_pages > 5 && current_page > 3 {
            html! {
                <button class="table-paging__btn">{ "..." }</button>
            }
        } else {
            html! {}
        }
    }

    fn view_pagination_delimiter_last(&self) -> Html {
        let total_pages = self.total_pages;
        let current_page = self.current_page;

        if total_pages > 5 && total_pages - current_page > 2 {
            html! {
                <button class="table-paging__btn">{ "..." }</button>
            }
        } else {
            html! {}
        }
    }

    fn view_pagination_button_last(&self) -> Html {
        let total_pages = self.total_pages;

        if total_pages > 5 {
            self.view_pagination_button(total_pages)
        } else {
            html! {}
        }
    }

    fn view_pagination_button_middle(&self) -> Html {
        let total_pages = self.total_pages;
        let current_page = self.current_page;
        let total_pages_safe = if total_pages < 2 { 2 } else { total_pages };

        if total_pages > 5 && current_page > 3 && current_page < total_pages_safe - 2 {
            self.view_pagination_button(current_page)
        } else {
            html! {}
        }
    }

    fn view_pagination_buttons_first(&self) -> Html {
        let total_pages = self.total_pages;
        let current_page = self.current_page;

        let max = if total_pages > 5 { 3 } else { 5 };
        let through = if total_pages > 5 { 4 } else { 6 };

        html! {
            { for (2..through).filter_map(|page| {
                if current_page <= max && total_pages >= page {
                    Some(self.view_pagination_button(page))
                } else {
                    None
                }
            }) }
        }
    }

    fn view_pagination_buttons_last(&self) -> Html {
        let total_pages = self.total_pages;
        let current_page = self.current_page;
        let total_pages_safe = if total_pages < 2 { 2 } else { total_pages };

        html! {
            {
                for (total_pages_safe-2..total_pages_safe).filter_map(|page| {
                    if total_pages > 5 && current_page > 3 && current_page >= total_pages_safe - 2 {
                        Some(self.view_pagination_button(page))
                    } else {
                        None
                    }
                })
            }
        }
    }
}