@ -14,6 +14,9 @@ use yew::prelude::*;
/// Displays a paginated list of quotes. Supports filtering by author name,
/// tag, and an optional date range (year granularity). Fetches from the API
/// whenever page, author, tag, or date state changes.
///
/// Filter controls are hidden behind a collapsible "Filters" toggle button.
/// The panel is collapsed by default when the page loads.
#[ function_component(BrowsePage) ]
pub fn browse_page ( ) -> Html {
let page = use_state ( | | 1 u32 ) ;
@ -25,6 +28,8 @@ pub fn browse_page() -> Html {
let quotes : UseStateHandle < Vec < Quote > > = use_state ( Vec ::new ) ;
let error : UseStateHandle < Option < String > > = use_state ( | | None ) ;
let loading = use_state ( | | true ) ;
// Filter panel is collapsed by default.
let filters_open = use_state ( | | false ) ;
// Fetch quotes whenever page, author, tag, or date bounds change
{
@ -143,29 +148,63 @@ pub fn browse_page() -> Html {
} )
} ;
let on_toggle_filters = {
let filters_open = filters_open . clone ( ) ;
Callback ::from ( move | _ : MouseEvent | {
filters_open . set ( ! * filters_open ) ;
} )
} ;
let toggle_label = if * filters_open {
"Filters \u{25b2}"
} else {
"Filters \u{25bc}"
} ;
html ! {
< div class = "page-browse" >
< h1 class = "page-browse__title" > { "Browse Quotes" } < / h1 >
< div class = "page-browse__filter-toggle-row" >
< button
class = "btn page-browse__filter-toggle"
type = "button"
onclick = { on_toggle_filters }
>
{ toggle_label }
< / button >
< / div >
if * filters_open {
< div class = "page-browse__filters" >
< div class = "page-browse__filter-row" >
< label class = "page-browse__filter-label" for = "browse-author" > { "Author:" } < / label >
< input
id = "browse-author"
class = "page-browse__filter-input"
type = "text"
placeholder = "Filter by author..."
value = { ( * author_filter ) . clone ( ) }
oninput = { on_author_input }
/ >
< / div >
< div class = "page-browse__filter-row" >
< label class = "page-browse__filter-label" for = "browse-tag" > { "Tag:" } < / label >
< input
id = "browse-tag"
class = "page-browse__filter-input"
type = "text"
placeholder = "Filter by tag..."
value = { ( * tag_filter ) . clone ( ) }
oninput = { on_tag_input }
/ >
< div class = "browse-filter__group" >
< label > { "From year" } < / label >
< / div >
< div class = "page-browse__filter-row" >
< label class = "page-browse__filter-label" > { "Date:" } < / label >
< div class = "page-browse__filter-date-group" >
< span class = "page-browse__filter-date-label" > { "after" } < / span >
< input
class = "page-browse__filter-input"
class = "page-browse__filter-input page-browse__filter-input--year "
type = "number"
min = "0"
max = "9999"
@ -173,11 +212,9 @@ pub fn browse_page() -> Html {
value = { ( * date_after_year ) . clone ( ) }
oninput = { on_date_after_year_input }
/ >
< / div >
< div class = "browse-filter__group" >
< label > { "To year" } < / label >
< span class = "page-browse__filter-date-label" > { "before" } < / span >
< input
class = "page-browse__filter-input "
class = "page-browse__filter-input page-browse__filter-input--year"
type = "number"
min = "0"
max = "9999"
@ -187,6 +224,8 @@ pub fn browse_page() -> Html {
/ >
< / div >
< / div >
< / div >
}
if * loading {
< p class = "page-browse__loading" > { "Loading..." } < / p >