// inventory.jsx — InventoryPage function InventoryPage({ data, onOpenDestiny }) { const seed = data || DOPO.SEED; const [typeFilter, setTypeFilter] = useState('all'); const [destinyFilter, setDestinyFilter] = useState('all'); const [search, setSearch] = useState(''); const allItems = useMemo(() => [ ...seed.services.map(s => ({ ...s, _type: 'digital' })), ...seed.assets.map(a => ({ ...a, _type: 'real' })), ], [seed.services, seed.assets]); const filtered = useMemo(() => { let list = allItems; if (typeFilter !== 'all') list = list.filter(i => i._type === typeFilter); if (destinyFilter === 'none') list = list.filter(i => !i.destiny); else if (destinyFilter !== 'all') list = list.filter(i => i.destiny === destinyFilter); if (search.trim()) { const q = search.toLowerCase(); list = list.filter(i => (i.name || '').toLowerCase().includes(q) || (i.email || '').toLowerCase().includes(q) || (i.category || '').toLowerCase().includes(q) ); } return list; }, [allItems, typeFilter, destinyFilter, search]); const catLabel = Object.fromEntries( [...DOPO.CATEGORIES.digital, ...DOPO.CATEGORIES.real].map(c => [c.id, c.label]) ); const destinyOptions = [ { id: 'all', label: 'Tutti' }, { id: 'people', label: 'Persone', color: 'var(--destiny-people)' }, { id: 'oblio', label: t.inventory.oblio, color: 'var(--destiny-oblio)' }, { id: 'hidden', label: t.inventory.hidden, color: 'var(--destiny-hidden)' }, { id: 'none', label: t.inventory.unassigned, color: 'var(--red-400)' }, ]; const destinyCounts = useMemo(() => ({ all: allItems.length, people: allItems.filter(i => i.destiny === 'people').length, oblio: allItems.filter(i => i.destiny === 'oblio').length, hidden: allItems.filter(i => i.destiny === 'hidden').length, none: allItems.filter(i => !i.destiny).length, }), [allItems]); return (
{t.inventory.add} } /> {/* Type tabs */}
{[ { id: 'all', label: 'Tutti', n: allItems.length }, { id: 'digital', label: t.inventory.tab_digital, n: seed.services.length }, { id: 'real', label: t.inventory.tab_real, n: seed.assets.length }, ].map(tab => ( ))}
{/* Destiny chips */}
{destinyOptions.map(opt => ( ))}
{/* Search */}
setSearch(e.target.value)} />
{/* Table */}
{filtered.length === 0 ? (
Nessun risultato per questa ricerca.
) : ( {filtered.map(item => { const { _type, ...cleanItem } = item; const itemType = _type === 'digital' ? 'service' : 'asset'; return ( onOpenDestiny(cleanItem, itemType)}> ); })}
Voce Tipo Categoria Destino Persone
{_type === 'digital' ? ( ) : (
{item.icon}
)}
{item.name}
{item.email && (
{item.email}
)}
{_type === 'real' ? 'Reale' : 'Digitale'} {catLabel[item.category] || item.category} {item.assignees && item.assignees.length > 0 ? : }
)}
); } Object.assign(window, { InventoryPage });