now responsive for mobile

This commit is contained in:
Connor Johnstone
2026-03-24 12:01:00 -04:00
parent 7c30f288cd
commit 29e6494e11
3 changed files with 125 additions and 8 deletions

View File

@@ -13,6 +13,7 @@ pub struct Props {
#[function_component(Navbar)]
pub fn navbar(props: &Props) -> Html {
let route = use_route::<Route>();
let sidebar_open = use_state(|| false);
let link = |to: Route, label: &str| {
let active = route.as_ref() == Some(&to);
@@ -24,16 +25,56 @@ pub fn navbar(props: &Props) -> Html {
let on_logout = {
let cb = props.on_logout.clone();
let sidebar_open = sidebar_open.clone();
Callback::from(move |e: MouseEvent| {
e.prevent_default();
sidebar_open.set(false);
cb.emit(());
})
};
let toggle = {
let sidebar_open = sidebar_open.clone();
Callback::from(move |_: MouseEvent| {
sidebar_open.set(!*sidebar_open);
})
};
let close_overlay = {
let sidebar_open = sidebar_open.clone();
Callback::from(move |_: MouseEvent| {
sidebar_open.set(false);
})
};
// Close sidebar when any nav link is clicked
let on_nav_click = {
let sidebar_open = sidebar_open.clone();
Callback::from(move |_: MouseEvent| {
sidebar_open.set(false);
})
};
let sidebar_class = if *sidebar_open {
"sidebar open"
} else {
"sidebar"
};
let overlay_class = if *sidebar_open {
"sidebar-overlay open"
} else {
"sidebar-overlay"
};
html! {
<div class="sidebar">
<>
<button class="hamburger" onclick={toggle}>
{ "\u{2630}" }
</button>
<div class={overlay_class} onclick={close_overlay}></div>
<div class={sidebar_class}>
<h1>{ "Shanty" }</h1>
<nav>
<nav onclick={on_nav_click}>
{ link(Route::Dashboard, "Dashboard") }
{ link(Route::Search, "Search") }
{ link(Route::Library, "Library") }
@@ -48,5 +89,6 @@ pub fn navbar(props: &Props) -> Html {
<a href="#" class="text-sm" onclick={on_logout}>{ "Logout" }</a>
</div>
</div>
</>
}
}

View File

@@ -281,17 +281,26 @@ pub fn dashboard() -> Html {
};
let scheduled_jobs_html = {
let next_pipeline = s.scheduled.as_ref().and_then(|sc| sc.next_pipeline.as_ref());
let next_pipeline = s
.scheduled
.as_ref()
.and_then(|sc| sc.next_pipeline.as_ref());
let next_monitor = s.scheduled.as_ref().and_then(|sc| sc.next_monitor.as_ref());
let pipeline_next_str = next_pipeline.map(|n| format_next_run(n)).unwrap_or_default();
let pipeline_next_str = next_pipeline
.map(|n| format_next_run(n))
.unwrap_or_default();
let monitor_next_str = next_monitor.map(|n| format_next_run(n)).unwrap_or_default();
let pipeline_last = s.scheduler.as_ref()
let pipeline_last = s
.scheduler
.as_ref()
.and_then(|sc| sc.get("pipeline"))
.and_then(|j| j.get("last_result"))
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
let monitor_last = s.scheduler.as_ref()
let monitor_last = s
.scheduler
.as_ref()
.and_then(|sc| sc.get("monitor"))
.and_then(|j| j.get("last_result"))
.and_then(|v| v.as_str())
@@ -483,7 +492,7 @@ pub fn dashboard() -> Html {
<tr><th>{ "Query" }</th><th>{ "Status" }</th><th>{ "Error" }</th></tr>
</thead>
<tbody>
{ for s.queue.items.iter().map(|item| html! {
{ for s.queue.items.iter().take(10).map(|item| html! {
<tr>
<td>{ &item.query }</td>
<td><StatusBadge status={item.status.clone()} /></td>
@@ -492,6 +501,11 @@ pub fn dashboard() -> Html {
})}
</tbody>
</table>
if s.queue.items.len() > 10 {
<p class="text-sm text-muted mt-1">
{ format!("and {} more...", s.queue.items.len() - 10) }
</p>
}
</div>
} else if s.queue.pending > 0 || s.queue.downloading > 0 {
<div class="card">
@@ -511,7 +525,7 @@ pub fn dashboard() -> Html {
<tr><th>{ "Title" }</th><th>{ "Artist" }</th><th>{ "Album" }</th><th>{ "MBID" }</th></tr>
</thead>
<tbody>
{ for tagging.items.iter().map(|t| html! {
{ for tagging.items.iter().take(10).map(|t| html! {
<tr>
<td>{ t.title.as_deref().unwrap_or("Unknown") }</td>
<td>{ t.artist.as_deref().unwrap_or("") }</td>
@@ -527,6 +541,11 @@ pub fn dashboard() -> Html {
})}
</tbody>
</table>
if tagging.items.len() > 10 {
<p class="text-sm text-muted mt-1">
{ format!("and {} more...", tagging.items.len() - 10) }
</p>
}
}
</div>
}