1
0

feat: rip queue page, library stats/queue links and on-loan chip

This commit is contained in:
2026-09-03 22:59:31 +02:00
parent 47858b1788
commit fc5797d929
5 changed files with 159 additions and 1 deletions

View File

@@ -0,0 +1,61 @@
import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { api } from '../api.js'
import type { Item } from '../types.js'
import Cover from '../components/Cover.js'
export default function QueuePage() {
const [items, setItems] = useState<Item[] | null>(null)
const [error, setError] = useState(false)
useEffect(() => {
void api
.listCollection({ ripped: 'not_ripped' })
.then((res) => setItems([...res.items].reverse()))
.catch(() => setError(true))
}, [])
function markRipped(id: number) {
void api
.setRip(id, true)
.then(() => setItems((list) => (list ?? []).filter((i) => i.id !== id)))
.catch(() => setError(true))
}
return (
<div className="space-y-3">
<p className="text-sm text-neutral-400">Rip queue oldest additions first.</p>
{error && <p className="text-sm text-red-400">Could not load the queue.</p>}
{items && items.length === 0 && (
<div className="py-12 text-center">
<p className="text-neutral-400">Nothing waiting to be ripped.</p>
<Link to="/scan" className="mt-2 inline-block text-sm text-emerald-400">
Scan something
</Link>
</div>
)}
{items &&
items.map((item) => (
<div key={item.id} className="flex items-center gap-3 rounded-xl border border-neutral-800 bg-neutral-900 p-3">
<Cover src={item.artworkUrl} alt="" className="size-12 shrink-0" />
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-medium">{item.title}</p>
<p className="truncate text-xs text-neutral-400">
{item.artist} · added {new Date(item.dateAdded + 'Z').toLocaleDateString()}
</p>
</div>
<button
type="button"
onClick={() => markRipped(item.id)}
className="shrink-0 rounded-lg bg-emerald-500 px-3 py-1.5 text-sm font-medium text-neutral-950"
>
Mark ripped
</button>
<Link to={`/item/${item.id}`} className="shrink-0 text-xs text-neutral-400">
details
</Link>
</div>
))}
</div>
)
}