1
0

feat: play button, last played, loan lend/return on item page

This commit is contained in:
2026-09-03 22:45:20 +02:00
parent b2711b2b79
commit ece18d125b
4 changed files with 179 additions and 20 deletions

View File

@@ -179,7 +179,14 @@ export async function registerCollectionRoutes(app: FastifyInstance): Promise<vo
const db = request.server.db
const row = getItem(db, request.user!.id, Number((request.params as { id: string }).id))
if (!row) return reply.code(404).send({ error: 'not_found' })
return { ...rowToItem(db, row), matchedAlbum: findMatchedAlbum(db, request.user!.id, row.id) }
const loan = db
.prepare('SELECT id, borrower, lent_at FROM loans WHERE item_id = ? AND returned_at IS NULL')
.get(row.id) as { id: number; borrower: string; lent_at: string } | undefined
return {
...rowToItem(db, row),
matchedAlbum: findMatchedAlbum(db, request.user!.id, row.id),
loan: loan ? { id: loan.id, borrower: loan.borrower, lentAt: loan.lent_at } : null,
}
})
app.delete('/api/collection/:id', { preHandler: [requireAuth] }, async (request, reply) => {

View File

@@ -56,6 +56,22 @@ describe('loans', () => {
await app.close()
})
it('detail route reports the active loan, null before lending', async () => {
const { app, cookie, itemId } = await appWithItem()
const before = await app.inject({ method: 'GET', url: `/api/collection/${itemId}`, ...auth(cookie) })
expect(before.json().loan).toBeNull()
await app.inject({
method: 'POST',
url: `/api/collection/${itemId}/loan`,
...auth(cookie),
payload: { borrower: 'Bob' },
})
const after = await app.inject({ method: 'GET', url: `/api/collection/${itemId}`, ...auth(cookie) })
expect(after.json().loan).toMatchObject({ borrower: 'Bob' })
await app.close()
})
it('validates borrower and ownership', async () => {
const { app, cookie, itemId } = await appWithItem()
const empty = await app.inject({