fix(packing): name everyone who brings a shared item

A common item brought by several members showed the first bringer's avatar
and a bare "+2". The tooltip only named the first person, and on the phone
neither the row nor the item sheet said who else brings it (discussion
#2782).

packingBringerNames lists the bringer and every contributor; the desktop
row, the phone row and the phone item sheet use it for "brought by".
This commit is contained in:
Maurice
2026-11-04 17:53:15 +01:00
parent b41f6e3542
commit da324121bd
5 changed files with 42 additions and 3 deletions
@@ -18,6 +18,7 @@ import { PopoverItem } from './PackingPopover'
import { POPOVER, POPOVER_CAPTION, POPOVER_DIVIDER } from './packingPopoverStyles'
import type { TripMember } from './usePackingListPanel'
import { NumericInput } from '../shared/NumericInput'
import { packingBringerNames } from './packingBringers'
interface ArtikelZeileProps {
item: PackingItem
@@ -226,7 +227,7 @@ export function ArtikelZeile({ item, tripId, categories, onCategoryChange: _onCa
</span>
)}
{!isPlaceholder && broughtBy && (
<span className="packing-row-badge" title={t('packing.broughtBy', { name: broughtBy })} aria-label={t('packing.broughtBy', { name: broughtBy })}
<span className="packing-row-badge" title={t('packing.broughtBy', { name: packingBringerNames(item) })} aria-label={t('packing.broughtBy', { name: packingBringerNames(item) })}
style={{ display: 'inline-flex', alignItems: 'center', gap: 3, flexShrink: 0 }}>
{ownerAvatar
? <img src={ownerAvatar} alt="" style={{ width: 20, height: 20, borderRadius: '50%', objectFit: 'cover', display: 'block' }} />
@@ -0,0 +1,22 @@
// FE-PACK-BRINGERS-001 to FE-PACK-BRINGERS-003
import { describe, expect, it } from 'vitest';
import { packingBringerNames } from './packingBringers';
describe('packingBringerNames', () => {
it('FE-PACK-BRINGERS-001: names the bringer first, then everyone who also brings it', () => {
const item = {
owner_username: 'anna',
contributors: [{ username: 'ben' }, { username: 'carla' }],
};
expect(packingBringerNames(item)).toBe('anna, ben, carla');
});
it('FE-PACK-BRINGERS-002: names a person once, even when listed twice', () => {
expect(packingBringerNames({ owner_username: 'anna', contributors: [{ username: 'anna' }] })).toBe('anna');
});
it('FE-PACK-BRINGERS-003: copes with an item without a bringer or contributors', () => {
expect(packingBringerNames({ owner_username: null, contributors: [{ username: 'ben' }] })).toBe('ben');
expect(packingBringerNames({})).toBe('');
});
});
@@ -0,0 +1,14 @@
interface BroughtItem {
owner_username?: string | null;
contributors?: { username: string }[] | null;
}
/**
* Everyone bringing a common item, as one readable list: its bringer first, then
* whoever also brings it. The row only has room for one avatar and a "+n", so this
* is what its tooltip and the item sheet name (#2782).
*/
export function packingBringerNames(item: BroughtItem): string {
const names = [item.owner_username, ...(item.contributors ?? []).map((c) => c.username)];
return [...new Set(names.filter((n): n is string => !!n))].join(', ');
}