import { FC, useCallback, useEffect, useEffectEvent, useMemo, useState } from 'react'; import { Button, Column, Flex, LayoutFurniIconImageView, Text } from '../../../common'; import { FurniItem } from '../../../hooks/furni-editor'; interface FurniEditorSearchViewProps { items: FurniItem[]; total: number; page: number; loading: boolean; onSearch: (query: string, type: string, page: number) => void; onSelect: (id: number) => void; } type SortField = 'id' | 'spriteId' | 'itemName' | 'publicName' | 'type' | 'interactionType'; type SortDir = 'asc' | 'desc'; const SortArrow: FC<{ field: SortField; active: SortField; dir: SortDir }> = ({ field, active, dir }) => { if(field !== active) return ; return { dir === 'asc' ? '▲' : '▼' }; }; export const FurniEditorSearchView: FC = props => { const { items, total, page, loading, onSearch, onSelect } = props; const [ query, setQuery ] = useState(''); const [ typeFilter, setTypeFilter ] = useState(''); const [ sortField, setSortField ] = useState('id'); const [ sortDir, setSortDir ] = useState('asc'); const initialSearch = useEffectEvent(() => onSearch('', '', 1)); useEffect(() => { initialSearch(); }, []); const handleSearch = useCallback(() => { onSearch(query, typeFilter, 1); }, [ query, typeFilter, onSearch ]); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if(e.key === 'Enter') handleSearch(); }, [ handleSearch ]); const handleSort = useCallback((field: SortField) => { setSortDir(prev => (sortField === field ? (prev === 'asc' ? 'desc' : 'asc') : 'asc')); setSortField(field); }, [ sortField ]); const handleTypeToggle = useCallback((type: string) => { setTypeFilter(prev => { const next = prev === type ? '' : type; onSearch(query, next, 1); return next; }); }, [ query, onSearch ]); const sortedItems = useMemo(() => { const sorted = [ ...items ]; sorted.sort((a, b) => { let va: string | number = a[sortField] ?? ''; let vb: string | number = b[sortField] ?? ''; if(typeof va === 'string') va = va.toLowerCase(); if(typeof vb === 'string') vb = vb.toLowerCase(); if(va < vb) return sortDir === 'asc' ? -1 : 1; if(va > vb) return sortDir === 'asc' ? 1 : -1; return 0; }); return sorted; }, [ items, sortField, sortDir ]); const totalPages = Math.ceil(total / 20); return ( Search setQuery(e.target.value) } onKeyDown={ handleKeyDown } /> { [ '', 's', 'i' ].map(t => ( )) } { total > 0 && { total } items found } { sortedItems.map(item => ( onSelect(item.id) } > )) } { items.length === 0 && !loading && }
handleSort('id') }> ID handleSort('spriteId') }> Sprite handleSort('itemName') }> Name handleSort('publicName') }> Public Name handleSort('type') }> Type handleSort('interactionType') }> Interaction
{ item.id } { item.spriteId } { item.itemName } { item.publicName } { item.type === 's' ? 'Floor' : 'Wall' } { item.interactionType || '-' }
No items found
{ totalPages > 1 && Page { page }/{ totalPages } }
); };