progress bars
This commit is contained in:
@@ -383,6 +383,35 @@ pub fn artist_page(props: &Props) -> Html {
|
||||
|
||||
let tc = album.track_count;
|
||||
|
||||
// Progress bar styles
|
||||
let owned_pct = if tc > 0 {
|
||||
(album.owned_tracks as f64 / tc as f64 * 100.0) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let owned_color = if album.owned_tracks >= tc && tc > 0 {
|
||||
"var(--success)"
|
||||
} else if album.owned_tracks > 0 {
|
||||
"var(--warning)"
|
||||
} else {
|
||||
"var(--text-muted)"
|
||||
};
|
||||
let owned_bar_style =
|
||||
format!("width:{owned_pct}%;background:{owned_color};");
|
||||
|
||||
let watched_pct = if tc > 0 {
|
||||
(album.watched_tracks as f64 / tc as f64 * 100.0) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let watched_color = if album.watched_tracks > 0 {
|
||||
"var(--accent)"
|
||||
} else {
|
||||
"var(--text-muted)"
|
||||
};
|
||||
let watched_bar_style =
|
||||
format!("width:{watched_pct}%;background:{watched_color};");
|
||||
|
||||
// Watch/Unwatch buttons for albums — show both when partially watched
|
||||
let is_fully_owned = album.status == "owned";
|
||||
let is_album_watched = album.status != "unwatched";
|
||||
@@ -473,23 +502,18 @@ pub fn artist_page(props: &Props) -> Html {
|
||||
<td class="text-muted">{ album.date.as_deref().unwrap_or("") }</td>
|
||||
<td>
|
||||
if tc > 0 {
|
||||
<span class="text-sm" style={
|
||||
if album.owned_tracks >= tc { "color: var(--success);" }
|
||||
else if album.owned_tracks > 0 { "color: var(--warning);" }
|
||||
else { "color: var(--text-muted);" }
|
||||
}>
|
||||
{ format!("{}/{}", album.owned_tracks, tc) }
|
||||
</span>
|
||||
<div class="progress-bar-wrap">
|
||||
<div class="progress-bar-fill" style={owned_bar_style}></div>
|
||||
<span class="progress-bar-text">{ format!("{}/{}", album.owned_tracks, tc) }</span>
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
if tc > 0 {
|
||||
<span class="text-sm" style={
|
||||
if album.watched_tracks > 0 { "color: var(--accent);" }
|
||||
else { "color: var(--text-muted);" }
|
||||
}>
|
||||
{ format!("{}/{}", album.watched_tracks, tc) }
|
||||
</span>
|
||||
<div class="progress-bar-wrap">
|
||||
<div class="progress-bar-fill" style={watched_bar_style}></div>
|
||||
<span class="progress-bar-text">{ format!("{}/{}", album.watched_tracks, tc) }</span>
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
<td>{ watch_btn }</td>
|
||||
|
||||
@@ -57,7 +57,6 @@ pub fn library_page() -> Html {
|
||||
<th>{ "Monitored" }</th>
|
||||
<th>{ "Owned" }</th>
|
||||
<th>{ "Watched" }</th>
|
||||
<th>{ "Tracks" }</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -134,6 +133,29 @@ pub fn library_page() -> Html {
|
||||
})
|
||||
};
|
||||
|
||||
// Pre-compute progress bar styles
|
||||
let owned_pct = if a.total_watched > 0 {
|
||||
(a.total_owned as f64 / a.total_watched as f64 * 100.0) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let owned_color = if a.total_owned >= a.total_watched && a.total_watched > 0 {
|
||||
"var(--success)"
|
||||
} else if a.total_owned > 0 {
|
||||
"var(--warning)"
|
||||
} else {
|
||||
"var(--text-muted)"
|
||||
};
|
||||
let owned_bar_style = format!("width:{owned_pct}%;background:{owned_color};");
|
||||
|
||||
let watched_pct = if a.total_items > 0 {
|
||||
(a.total_watched as f64 / a.total_items as f64 * 100.0) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let watched_color = if a.total_watched > 0 { "var(--accent)" } else { "var(--text-muted)" };
|
||||
let watched_bar_style = format!("width:{watched_pct}%;background:{watched_color};");
|
||||
|
||||
html! {
|
||||
<tr>
|
||||
<td>
|
||||
@@ -148,32 +170,22 @@ pub fn library_page() -> Html {
|
||||
</td>
|
||||
if a.enriched {
|
||||
<td>
|
||||
<span class="text-sm" style={
|
||||
if a.total_owned >= a.total_watched && a.total_watched > 0 { "color: var(--success);" }
|
||||
else if a.total_owned > 0 { "color: var(--warning);" }
|
||||
else { "color: var(--text-muted);" }
|
||||
}>
|
||||
{ format!("{}/{}", a.total_owned, a.total_watched) }
|
||||
</span>
|
||||
<div class="progress-bar-wrap">
|
||||
<div class="progress-bar-fill" style={owned_bar_style.clone()}></div>
|
||||
<span class="progress-bar-text">{ format!("{}/{}", a.total_owned, a.total_watched) }</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-sm" style={
|
||||
if a.total_watched > 0 { "color: var(--accent);" }
|
||||
else { "color: var(--text-muted);" }
|
||||
}>
|
||||
{ format!("{}/{}", a.total_watched, a.total_items) }
|
||||
</span>
|
||||
<div class="progress-bar-wrap">
|
||||
<div class="progress-bar-fill" style={watched_bar_style.clone()}></div>
|
||||
<span class="progress-bar-text">{ format!("{}/{}", a.total_watched, a.total_items) }</span>
|
||||
</div>
|
||||
</td>
|
||||
} else {
|
||||
<td colspan="2" class="text-sm text-muted loading">
|
||||
{ "Awaiting artist enrichment..." }
|
||||
</td>
|
||||
}
|
||||
<td class="text-muted text-sm">
|
||||
if a.enriched && a.total_items > 0 {
|
||||
{ a.total_items }
|
||||
}
|
||||
</td>
|
||||
<td class="actions">
|
||||
<button class="btn btn-sm btn-lib"
|
||||
onclick={on_watch}
|
||||
|
||||
@@ -228,7 +228,7 @@ a:hover { color: var(--accent-hover); }
|
||||
/* Tables */
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th, td { text-align: left; padding: 0.75rem; border-bottom: 1px solid var(--border); }
|
||||
th { color: var(--text-secondary); font-weight: 600; font-size: 0.85rem; text-transform: uppercase; }
|
||||
th { color: var(--text-secondary); font-weight: 600; font-size: 0.85rem; text-transform: uppercase; text-align: center; }
|
||||
tr:hover { background: var(--bg-card); }
|
||||
|
||||
/* Buttons */
|
||||
@@ -248,6 +248,36 @@ tr:hover { background: var(--bg-card); }
|
||||
.btn-danger { background: var(--danger); color: white; }
|
||||
.btn-secondary { background: var(--bg-card); color: var(--text-primary); border: 1px solid var(--border); }
|
||||
.btn-sm { padding: 0.25rem 0.5rem; font-size: 0.8rem; }
|
||||
/* Progress bars for library columns */
|
||||
.progress-bar-wrap {
|
||||
position: relative;
|
||||
background: var(--bg-card);
|
||||
border-radius: 4px;
|
||||
height: 1.4rem;
|
||||
min-width: 4.5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.progress-bar-fill {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
opacity: 0.3;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
.progress-bar-text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.btn-fixed { min-width: 5.5rem; text-align: center; }
|
||||
.btn-lib { min-width: 4.5rem; text-align: center; padding-left: 0.25rem; padding-right: 0.25rem; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user