FEAT-12a: multi-select bulk 'Zur Abgabe stellen' on the Tiere list

This commit is contained in:
2026-06-06 07:13:30 +02:00
parent aa79f9dbe5
commit 07dd5c9b8e
2 changed files with 81 additions and 3 deletions

View File

@@ -1,12 +1,13 @@
import { useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import { de } from '../strings/de'
import { listGerbils } from '../api/gerbils'
import { listGerbils, updateGerbil } from '../api/gerbils'
import { listColorVarieties } from '../api/lookups'
import { andFilter, condition, type GridifyQuery } from '../api/gridify'
import { GENDERS, GERBIL_STATUSES, type Gender, type GerbilStatus } from '../api/types'
import { useApi } from '../hooks/useApi'
import { useApi, useMutation } from '../hooks/useApi'
import { formatDate, genderLabel, statusLabel } from '../format/labels'
import './gerbils.css'
const PAGE_SIZE = 20
@@ -64,6 +65,26 @@ export default function GerbilsPage() {
const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE))
const items = gerbils.data?.items ?? []
// Multi-select bulk "Zur Abgabe stellen".
const [selected, setSelected] = useState<Set<string>>(new Set())
const toggleSelect = (id: string) =>
setSelected((prev) => {
const next = new Set(prev)
if (next.has(id)) next.delete(id)
else next.add(id)
return next
})
const bulkForSale = useMutation((ids: string[]) =>
Promise.all(ids.map((id) => updateGerbil(id, { status: 'ForSale' }))),
)
async function markSelectedForSale() {
const result = await bulkForSale.run([...selected])
if (result.ok) {
setSelected(new Set())
gerbils.reload()
}
}
return (
<section className="page">
<header className="page-head">
@@ -159,10 +180,34 @@ export default function GerbilsPage() {
<p className="muted">{t.empty}</p>
)}
{selected.size > 0 && (
<div className="bulk-bar">
<span>
{selected.size} {t.countLabel}
</span>
<button
type="button"
className="btn btn--primary"
disabled={bulkForSale.pending}
onClick={markSelectedForSale}
>
{de.pages.abgabe.markMultiAction}
</button>
{bulkForSale.error && <span className="error-text">{bulkForSale.error}</span>}
</div>
)}
{items.length > 0 && (
<ul className="card-list">
{items.map((g) => (
<li key={g.id}>
<li key={g.id} className="gerbil-row">
<input
type="checkbox"
className="gerbil-row__check"
checked={selected.has(g.id)}
onChange={() => toggleSelect(g.id)}
aria-label={g.name}
/>
<Link to={`/rennmaeuse/${g.id}`} className="gerbil-card">
<span className="gerbil-card__name">{g.name}</span>
<span className={`badge badge--${g.status.toLowerCase()}`}>