90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
'use client';
|
|
|
|
import shared from '../../styles/shared.module.css';
|
|
import styles from '../../styles/Customizations.module.css';
|
|
import { DB_BASE_URL } from '../../lib/db';
|
|
import { Character, RoleFilter } from './types';
|
|
|
|
type Props = {
|
|
filteredChars: Character[];
|
|
charSearch: string;
|
|
charRole: RoleFilter;
|
|
charFullyUnlocked: Map<number, boolean>;
|
|
onSelect: (idx: number) => void;
|
|
onSearchChange: (s: string) => void;
|
|
onRoleChange: (r: RoleFilter) => void;
|
|
onUnlockShownCosmetics: () => void;
|
|
onLockShownCosmetics: () => void;
|
|
};
|
|
|
|
const getCharIconUrl = (iconFilePath: string) => {
|
|
const file = (iconFilePath.split('/').pop() ?? '').split('.')[0];
|
|
return `${DB_BASE_URL}/icons/character-icons/${file}.png`;
|
|
};
|
|
|
|
export default function CharacterPicker({
|
|
filteredChars,
|
|
charSearch,
|
|
charRole,
|
|
charFullyUnlocked,
|
|
onSelect,
|
|
onSearchChange,
|
|
onRoleChange,
|
|
onUnlockShownCosmetics,
|
|
onLockShownCosmetics,
|
|
}: Props) {
|
|
return (
|
|
<>
|
|
<div className={shared.toolbar}>
|
|
<input
|
|
className={shared.searchInput}
|
|
type="text"
|
|
placeholder="Search character..."
|
|
value={charSearch}
|
|
onChange={e => onSearchChange(e.target.value)}
|
|
/>
|
|
<div className={shared.roleFilter}>
|
|
{(['all', 'survivors', 'killers'] as RoleFilter[]).map(r => (
|
|
<button
|
|
key={r}
|
|
className={`${shared.roleBtn} ${charRole === r ? shared.roleBtnActive : ''}`}
|
|
onClick={() => onRoleChange(r)}
|
|
>
|
|
{r}
|
|
</button>
|
|
))}
|
|
</div>
|
|
<span className={shared.spacer} />
|
|
<span className={shared.resultCount}>{filteredChars.length} shown</span>
|
|
<button className={shared.unlockAllBtn} onClick={onUnlockShownCosmetics}>
|
|
Unlock Shown Cosmetics
|
|
</button>
|
|
<button className={shared.lockAllBtn} onClick={onLockShownCosmetics}>
|
|
Lock Shown Cosmetics
|
|
</button>
|
|
</div>
|
|
|
|
<div className={styles.charGrid}>
|
|
{filteredChars.map(char => {
|
|
const fullyUnlocked = charFullyUnlocked.get(char.idx) ?? false;
|
|
return (
|
|
<div
|
|
key={char.idx}
|
|
className={`${styles.charCard} ${fullyUnlocked ? styles.charCardFullyUnlocked : ''}`}
|
|
onClick={() => onSelect(char.idx)}
|
|
>
|
|
<img
|
|
className={styles.charCardIcon}
|
|
src={getCharIconUrl(char.iconFilePath)}
|
|
alt={char.name}
|
|
loading="lazy"
|
|
/>
|
|
<span className={styles.charCardName}>{char.name}</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|