"use client"; import { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { Badge } from "@/components/ui/badge"; import type { GroupWithCount } from "@/types"; interface GroupBadgesProps { selectedGroupId: string | null; onGroupSelect: (groupId: string) => void; refreshTrigger?: number; groups: GroupWithCount[]; isLoading: boolean; } export function GroupBadges({ selectedGroupId, onGroupSelect, groups, isLoading, }: GroupBadgesProps) { const { t } = useTranslation(); const scrollContainerRef = useRef(null); const [showLeftFade, setShowLeftFade] = useState(false); const [showRightFade, setShowRightFade] = useState(false); const [isDragging, setIsDragging] = useState(false); const dragStartRef = useRef<{ x: number; scrollLeft: number } | null>(null); const hasMovedRef = useRef(false); const clickBlockedRef = useRef(false); const checkScrollPosition = useCallback(() => { const container = scrollContainerRef.current; if (!container) return; const { scrollLeft, scrollWidth, clientWidth } = container; setShowLeftFade(scrollLeft > 0); setShowRightFade(scrollLeft < scrollWidth - clientWidth - 1); }, []); const handleMouseDown = useCallback((e: React.MouseEvent) => { const container = scrollContainerRef.current; if (!container) return; e.preventDefault(); dragStartRef.current = { x: e.clientX, scrollLeft: container.scrollLeft, }; hasMovedRef.current = false; setIsDragging(true); container.style.cursor = "grabbing"; container.style.userSelect = "none"; }, []); const handleMouseMove = useCallback( (e: MouseEvent) => { if (!isDragging || !dragStartRef.current) return; const container = scrollContainerRef.current; if (!container) return; const deltaX = e.clientX - dragStartRef.current.x; const distance = Math.abs(deltaX); if (distance > 5) { hasMovedRef.current = true; } container.scrollLeft = dragStartRef.current.scrollLeft - deltaX; checkScrollPosition(); }, [isDragging, checkScrollPosition], ); const handleMouseUp = useCallback(() => { if (!isDragging) return; const container = scrollContainerRef.current; if (container) { container.style.cursor = ""; container.style.userSelect = ""; } clickBlockedRef.current = hasMovedRef.current; setIsDragging(false); dragStartRef.current = null; setTimeout(() => { hasMovedRef.current = false; clickBlockedRef.current = false; }, 100); }, [isDragging]); useEffect(() => { if (isDragging) { document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); return () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; } }, [isDragging, handleMouseMove, handleMouseUp]); useEffect(() => { const container = scrollContainerRef.current; if (!container) return; checkScrollPosition(); container.addEventListener("scroll", checkScrollPosition); const resizeObserver = new ResizeObserver(checkScrollPosition); resizeObserver.observe(container); return () => { container.removeEventListener("scroll", checkScrollPosition); resizeObserver.disconnect(); }; }, [checkScrollPosition]); useEffect(() => { if (groups.length === 0) { setShowLeftFade(false); setShowRightFade(false); return; } const container = scrollContainerRef.current; if (!container) return; requestAnimationFrame(() => { requestAnimationFrame(() => { checkScrollPosition(); }); }); }, [groups, checkScrollPosition]); if (isLoading && !groups.length) { return (
Loading groups...
); } return (
{showLeftFade && (
)} {showRightFade && (
)}
{groups.map((group) => ( { if (hasMovedRef.current || clickBlockedRef.current) { e.preventDefault(); e.stopPropagation(); return; } onGroupSelect( selectedGroupId === group.id ? "default" : group.id, ); }} onMouseDown={(e) => { if (isDragging) { e.preventDefault(); e.stopPropagation(); } }} > {group.id === "default" ? t("groups.defaultGroup") : group.name} {group.count} ))}
); }