diff --git a/app/components/dashboard/project-management/digital-innovation-page.tsx b/app/components/dashboard/project-management/digital-innovation-page.tsx index ba28b27..0001494 100644 --- a/app/components/dashboard/project-management/digital-innovation-page.tsx +++ b/app/components/dashboard/project-management/digital-innovation-page.tsx @@ -181,6 +181,8 @@ export function DigitalInnovationPage() { // const [avarage, setAvarage] = useState(0); const observerRef = useRef(null); const fetchingRef = useRef(false); + const scrollTimeoutRef = useRef(null); + const scrollContainerRef = useRef(null); // Selection handlers const handleSelectAll = () => { @@ -346,10 +348,10 @@ export function DigitalInnovationPage() { }; const loadMore = useCallback(() => { - if (hasMore && !loading) { + if (hasMore && !loading && !loadingMore && !fetchingRef.current) { setCurrentPage((prev) => prev + 1); } - }, [hasMore, loading]); + }, [hasMore, loading, loadingMore]); useEffect(() => { fetchTable(true); @@ -363,28 +365,41 @@ export function DigitalInnovationPage() { } }, [currentPage]); + // Infinite scroll observer with debouncing useEffect(() => { - const scrollContainer = document.querySelector(".overflow-auto"); + const scrollContainer = scrollContainerRef.current; const handleScroll = () => { - if (!scrollContainer || !hasMore) return; + if (!scrollContainer || !hasMore || loadingMore || fetchingRef.current) return; - const { scrollTop, scrollHeight, clientHeight } = scrollContainer; - const scrollPercentage = (scrollTop + clientHeight) / scrollHeight; - - if (scrollPercentage == 1) { - loadMore(); + // Clear previous timeout + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current); } + + // Debounce scroll events + scrollTimeoutRef.current = setTimeout(() => { + const { scrollTop, scrollHeight, clientHeight } = scrollContainer; + const scrollPercentage = (scrollTop + clientHeight) / scrollHeight; + + // Trigger load more when scrolled to 95% of the container + if (scrollPercentage >= 0.95) { + loadMore(); + } + }, 150); }; if (scrollContainer) { - scrollContainer.addEventListener("scroll", handleScroll); + scrollContainer.addEventListener("scroll", handleScroll, { passive: true }); } return () => { if (scrollContainer) { scrollContainer.removeEventListener("scroll", handleScroll); } + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current); + } }; }, [loadMore, hasMore, loadingMore]); diff --git a/app/components/dashboard/project-management/mange-ideas-tech-page.tsx b/app/components/dashboard/project-management/mange-ideas-tech-page.tsx index d533981..9d44cf3 100644 --- a/app/components/dashboard/project-management/mange-ideas-tech-page.tsx +++ b/app/components/dashboard/project-management/mange-ideas-tech-page.tsx @@ -244,6 +244,8 @@ export function ManageIdeasTechPage() { }); const observerRef = useRef(null); const fetchingRef = useRef(false); + const scrollTimeoutRef = useRef(null); + const scrollContainerRef = useRef(null); const fetchProjects = async (reset = false) => { // Prevent concurrent API calls @@ -341,10 +343,10 @@ export function ManageIdeasTechPage() { }; const loadMore = useCallback(() => { - if (hasMore && !loading) { + if (hasMore && !loading && !loadingMore && !fetchingRef.current) { setCurrentPage((prev) => prev + 1); } - }, [hasMore, loading]); + }, [hasMore, loading, loadingMore]); useEffect(() => { fetchProjects(true); @@ -357,30 +359,41 @@ export function ManageIdeasTechPage() { } }, [currentPage]); - // Infinite scroll observer + // Infinite scroll observer with debouncing useEffect(() => { - const scrollContainer = document.querySelector(".overflow-auto"); + const scrollContainer = scrollContainerRef.current; const handleScroll = () => { - if (!scrollContainer || !hasMore) return; + if (!scrollContainer || !hasMore || loadingMore || fetchingRef.current) return; - const { scrollTop, scrollHeight, clientHeight } = scrollContainer; - const scrollPercentage = (scrollTop + clientHeight) / scrollHeight; - - // Trigger load more when scrolled to 90% of the container - if (scrollPercentage == 1) { - loadMore(); + // Clear previous timeout + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current); } + + // Debounce scroll events + scrollTimeoutRef.current = setTimeout(() => { + const { scrollTop, scrollHeight, clientHeight } = scrollContainer; + const scrollPercentage = (scrollTop + clientHeight) / scrollHeight; + + // Trigger load more when scrolled to 95% of the container + if (scrollPercentage >= 0.95) { + loadMore(); + } + }, 150); }; if (scrollContainer) { - scrollContainer.addEventListener("scroll", handleScroll); + scrollContainer.addEventListener("scroll", handleScroll, { passive: true }); } return () => { if (scrollContainer) { scrollContainer.removeEventListener("scroll", handleScroll); } + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current); + } }; }, [loadMore, hasMore, loadingMore]); @@ -656,7 +669,7 @@ export function ManageIdeasTechPage() {
- +
{columns.map((column) => ( diff --git a/app/components/dashboard/project-management/project-management-page.tsx b/app/components/dashboard/project-management/project-management-page.tsx index 8e76f6a..878989e 100644 --- a/app/components/dashboard/project-management/project-management-page.tsx +++ b/app/components/dashboard/project-management/project-management-page.tsx @@ -167,6 +167,8 @@ export function ProjectManagementPage() { }); const observerRef = useRef(null); const fetchingRef = useRef(false); + const scrollTimeoutRef = useRef(null); + const scrollContainerRef = useRef(null); const fetchProjects = async (reset = false) => { // Prevent concurrent API calls @@ -264,10 +266,10 @@ export function ProjectManagementPage() { }; const loadMore = useCallback(() => { - if (hasMore && !loading) { + if (hasMore && !loading && !loadingMore && !fetchingRef.current) { setCurrentPage((prev) => prev + 1); } - }, [hasMore, loading]); + }, [hasMore, loading, loadingMore]); useEffect(() => { fetchProjects(true); @@ -280,29 +282,43 @@ export function ProjectManagementPage() { } }, [currentPage]); - // Infinite scroll observer + // Infinite scroll observer with debouncing useEffect(() => { - const scrollContainer = document.querySelector(".overflow-auto"); - const handleScroll = () => { - if (!scrollContainer || !hasMore) return; + const scrollContainer = scrollContainerRef.current; - const { scrollTop, scrollHeight, clientHeight } = scrollContainer; - const scrollPercentage = (scrollTop + clientHeight) / scrollHeight; - // Trigger load more when scrolled to 90% of the container - if (scrollPercentage == 1 || scrollPercentage == .9) { - loadMore(); + const handleScroll = () => { + if (!scrollContainer || !hasMore || loadingMore || fetchingRef.current) return; + + // Clear previous timeout + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current); } + + // Debounce scroll events + scrollTimeoutRef.current = setTimeout(() => { + const { scrollTop, scrollHeight, clientHeight } = scrollContainer; + const scrollPercentage = (scrollTop + clientHeight) / scrollHeight; + + // Trigger load more when scrolled to 95% of the container + if (scrollPercentage >= 0.95) { + loadMore(); + } + }, 150); }; + if (scrollContainer) { - scrollContainer.addEventListener("scroll", handleScroll); + scrollContainer.addEventListener("scroll", handleScroll, { passive: true }); } return () => { if (scrollContainer) { scrollContainer.removeEventListener("scroll", handleScroll); } + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current); + } }; - }, [loadMore, hasMore]); + }, [loadMore, hasMore, loadingMore]); const handleSort = (field: string) => { fetchingRef.current = false; // Reset fetching state on sort @@ -754,7 +770,7 @@ export function ProjectManagementPage() {
-
+
diff --git a/app/components/ui/table.tsx b/app/components/ui/table.tsx index d5eae2e..7aa9a12 100644 --- a/app/components/ui/table.tsx +++ b/app/components/ui/table.tsx @@ -4,11 +4,12 @@ import { cn } from "~/lib/utils" interface TableProps extends React.HTMLAttributes { containerClassName?: string + containerRef?: React.RefObject } const Table = React.forwardRef( - ({ className, containerClassName, ...props }, ref) => ( -
+ ({ className, containerClassName, containerRef, ...props }, ref) => ( +