Files
photos/frontend/src/components/SelectionBar.jsx
T
nils 61f1bd1474
ci / docker (push) Successful in 13m28s
Bulk delete, editable share links, gallery filter fix
- shift-click selects ranges in the gallery; selection bar gains
  'Delete N' with a single confirm (POST /api/photos/delete)
- PATCH /api/shares/{id}: allow_download and expiry editable in place,
  token and client feedback preserved
- Gallery: re-attach ResizeObserver via callback ref — after a filter
  with zero matches the gallery stayed blank at width 0
2026-07-17 16:30:26 +02:00

59 lines
1.4 KiB
React

export function fmtBytes(bytes) {
if (!bytes) return '0 B'
const units = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.min(Math.floor(Math.log2(bytes) / 10), units.length - 1)
const value = bytes / 2 ** (10 * i)
return `${value >= 100 || i === 0 ? Math.round(value) : value.toFixed(1)} ${units[i]}`
}
export default function SelectionBar({
count,
total,
selectedBytes,
totalBytes,
onSelectAll,
onClear,
onDownload,
onDownloadAll,
onDelete,
}) {
if (total === 0) return null
if (count === 0) {
return (
<div className="select-bar">
<span className="select-count">
{total} photo{total === 1 ? '' : 's'} · {fmtBytes(totalBytes)}
</span>
<button className="btn btn-primary" onClick={onDownloadAll}>
Download all as ZIP
</button>
</div>
)
}
return (
<div className="select-bar">
<span className="select-count">
{count} of {total} selected
</span>
{count < total && (
<button className="btn" onClick={onSelectAll}>
Select all
</button>
)}
<button className="btn" onClick={onClear}>
Clear
</button>
<button className="btn btn-primary" onClick={onDownload}>
Download {count} as ZIP ({fmtBytes(selectedBytes)})
</button>
{onDelete && (
<button className="btn btn-danger" onClick={onDelete}>
Delete {count}
</button>
)}
</div>
)
}