feat: add Addons
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useMemo } from 'react';
|
||||
import shared from '../../styles/shared.module.css';
|
||||
import styles from '../../styles/Items.module.css';
|
||||
import QuantityCard from '../../components/QuantityCard';
|
||||
import { Addon, getAddonIconUrl, randInRange } from './types';
|
||||
|
||||
type Props = {
|
||||
addons: Addon[];
|
||||
quantities: Record<string, number>;
|
||||
randMin: number;
|
||||
randMax: number;
|
||||
onSetQty: (id: string, qty: number) => void;
|
||||
};
|
||||
|
||||
export default function AddonGrid({ addons, quantities, randMin, randMax, onSetQty }: Props) {
|
||||
const [search, setSearch] = useState('');
|
||||
const [roleFilter, setRoleFilter] = useState<'all' | 'killer' | 'survivor'>('all');
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
return addons.filter(addon => {
|
||||
if (roleFilter === 'killer' && addon.role !== 1) return false;
|
||||
if (roleFilter === 'survivor' && addon.role !== 2) return false;
|
||||
if (search.trim() && !addon.name.toLowerCase().includes(search.toLowerCase())) return false;
|
||||
return true;
|
||||
});
|
||||
}, [addons, search, roleFilter]);
|
||||
|
||||
const handleGive100Visible = () => filtered.forEach(a => onSetQty(a.id, 100));
|
||||
const handleRandVisible = () => filtered.forEach(a => onSetQty(a.id, randInRange(randMin, randMax)));
|
||||
const handleLockVisible = () => filtered.forEach(a => onSetQty(a.id, 0));
|
||||
|
||||
const activeCount = Object.values(quantities).filter(q => q > 0).length;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={shared.toolbar}>
|
||||
<input
|
||||
className={shared.searchInput}
|
||||
type="text"
|
||||
placeholder="Search addons..."
|
||||
value={search}
|
||||
onChange={e => setSearch(e.target.value)}
|
||||
/>
|
||||
|
||||
<div className={shared.roleFilter}>
|
||||
<button className={`${shared.roleBtn} ${roleFilter === 'all' ? shared.roleBtnActive : ''}`} onClick={() => setRoleFilter('all')}>All</button>
|
||||
<button className={`${shared.roleBtn} ${roleFilter === 'survivor' ? shared.roleBtnActive : ''}`} onClick={() => setRoleFilter('survivor')}>Survivor</button>
|
||||
<button className={`${shared.roleBtn} ${roleFilter === 'killer' ? shared.roleBtnActive : ''}`} onClick={() => setRoleFilter('killer')}>Killer</button>
|
||||
</div>
|
||||
|
||||
<span className={shared.spacer} />
|
||||
<span className={shared.resultCount}>{filtered.length} shown · {activeCount} active out of {addons.length} total</span>
|
||||
|
||||
<button className={shared.unlockAllBtn} onClick={handleGive100Visible}>Set all to 100</button>
|
||||
<button className={styles.randBtn} onClick={handleRandVisible}>Randomize</button>
|
||||
<button className={shared.lockAllBtn} onClick={handleLockVisible}>Remove all visible</button>
|
||||
</div>
|
||||
|
||||
{filtered.length === 0 ? (
|
||||
<div className={shared.empty}>No addons match</div>
|
||||
) : (
|
||||
<div className={styles.grid}>
|
||||
{filtered.map(addon => (
|
||||
<QuantityCard
|
||||
key={addon.id}
|
||||
id={addon.id}
|
||||
name={addon.name}
|
||||
iconUrl={getAddonIconUrl(addon.iconFilePath)}
|
||||
qty={quantities[addon.id] ?? 0}
|
||||
randMin={randMin}
|
||||
randMax={randMax}
|
||||
onSetQty={onSetQty}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user