import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { FaPlus } from 'react-icons/fa'; import { GetConfigurationValue, LocalizeText } from '../../../../../api'; import { LayoutBadgeImageView } from '../../../../../common'; import { useInventoryBadges } from '../../../../../hooks'; interface InfoStandBadgeSlotProps { slotIndex: number; badgeCode?: string; isOwnUser: boolean; } const BadgeMiniPicker: FC<{ onSelect: (badgeCode: string) => void; onClose: () => void; activeBadgeCodes: (string | null)[]; }> = ({ onSelect, onClose, activeBadgeCodes }) => { const { badgeCodes = [], requestBadges = null } = useInventoryBadges(); const ref = useRef(null); const [ search, setSearch ] = useState(''); useEffect(() => { if(badgeCodes.length === 0) requestBadges(); }, []); const activeSet = new Set(activeBadgeCodes.filter(Boolean)); const availableBadges = badgeCodes.filter(code => !activeSet.has(code)); const filtered = search.length > 0 ? availableBadges.filter(code => code.toLowerCase().includes(search.toLowerCase())) : availableBadges; useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if(ref.current && !ref.current.contains(event.target as Node)) onClose(); }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, [ onClose ]); return (
e.stopPropagation() }> setSearch(e.target.value) } /> { badgeCodes.length === 0 ? { LocalizeText('generic.loading') } : (
{ filtered.slice(0, 40).map(code => (
onSelect(code) }>
)) } { filtered.length === 0 && ( { LocalizeText('generic.no_results_found') } ) }
) }
); }; export const InfoStandBadgeSlotView: FC = ({ slotIndex, badgeCode: badgeCodeFromProps, isOwnUser }) => { const { activeBadgeCodes = [], setBadgeAtSlot = null, swapBadges = null, removeBadge = null, requestBadges = null } = useInventoryBadges(); const [ isDragOver, setIsDragOver ] = useState(false); const [ isDragging, setIsDragging ] = useState(false); const [ justDropped, setJustDropped ] = useState(false); const [ showPicker, setShowPicker ] = useState(false); const hookInitialized = activeBadgeCodes.length > 0; // Load badge data for own user so hook is initialized before any DnD useEffect(() => { if(isOwnUser && !hookInitialized) requestBadges(); }, [ isOwnUser, hookInitialized, requestBadges ]); const hookBadge = hookInitialized ? (activeBadgeCodes[slotIndex] ?? null) : null; // Once hook has data, use ONLY hook data for own user (no stale props fallback) const badgeCode = isOwnUser ? (hookInitialized ? hookBadge : (badgeCodeFromProps ?? null)) : (badgeCodeFromProps ?? null); const onDragStart = useCallback((event: React.DragEvent) => { if(!badgeCode || !isOwnUser) return; event.dataTransfer.setData('badgeCode', badgeCode); event.dataTransfer.setData('infostandSlot', slotIndex.toString()); event.dataTransfer.effectAllowed = 'move'; setIsDragging(true); const badgeUrl = GetConfigurationValue('badge.asset.url').replace('%badgename%', badgeCode); const img = new Image(); img.src = badgeUrl; event.dataTransfer.setDragImage(img, 20, 20); }, [ badgeCode, slotIndex, isOwnUser ]); const onDragEnd = useCallback(() => setIsDragging(false), []); const onDragOver = useCallback((event: React.DragEvent) => { if(!isOwnUser) return; event.preventDefault(); event.dataTransfer.dropEffect = 'move'; setIsDragOver(true); }, [ isOwnUser ]); const onDragLeave = useCallback(() => setIsDragOver(false), []); const onDrop = useCallback((event: React.DragEvent) => { event.preventDefault(); setIsDragOver(false); if(!isOwnUser) return; const droppedBadgeCode = event.dataTransfer.getData('badgeCode'); const sourceSlotStr = event.dataTransfer.getData('infostandSlot'); if(!droppedBadgeCode) return; if(sourceSlotStr !== '') { const sourceSlot = parseInt(sourceSlotStr); if(sourceSlot !== slotIndex) swapBadges(sourceSlot, slotIndex); } else { setBadgeAtSlot(droppedBadgeCode, slotIndex); } setJustDropped(true); setTimeout(() => setJustDropped(false), 300); }, [ isOwnUser, slotIndex, swapBadges, setBadgeAtSlot ]); const handleSlotClick = useCallback(() => { if(!isOwnUser || badgeCode) return; setShowPicker(true); }, [ isOwnUser, badgeCode ]); const handleDoubleClick = useCallback(() => { if(!isOwnUser || !badgeCode) return; removeBadge(badgeCode); }, [ isOwnUser, badgeCode, removeBadge ]); const handlePickerSelect = useCallback((code: string) => { setBadgeAtSlot(code, slotIndex); setShowPicker(false); }, [ setBadgeAtSlot, slotIndex ]); return (
{ badgeCode ? : isOwnUser && }
{ showPicker && ( setShowPicker(false) } onSelect={ handlePickerSelect } /> ) }
); };