diff --git a/app/components/dashboard/dashboard-home.tsx b/app/components/dashboard/dashboard-home.tsx
index 35feda2..23392a3 100644
--- a/app/components/dashboard/dashboard-home.tsx
+++ b/app/components/dashboard/dashboard-home.tsx
@@ -230,7 +230,7 @@ export function DashboardHome() {
style={{ height: `${Math.random() * 80 + 20}%` }}
>
-
+
مقاله:
@@ -791,7 +791,7 @@ export function DashboardHome() {
-
+
برگزاری رویداد:
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/progress.tsx b/app/components/ui/progress.tsx
index 8e11734..8fdf955 100644
--- a/app/components/ui/progress.tsx
+++ b/app/components/ui/progress.tsx
@@ -16,13 +16,11 @@ const Progress = React.forwardRef<
{...props}
>
۰%
- {formatNumber(Math.ceil(value || 0 * 10) / 10)}%
- {formatNumber(.2)}%
))
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) => (
+