Rom89823974978 commited on
Commit
be1c0ed
·
1 Parent(s): e259887
frontend/src/components/Dashboard.tsx CHANGED
@@ -72,29 +72,27 @@ const Dashboard: React.FC<DashboardProps> = ({
72
  const [orgInput, setOrgInput] = useState("");
73
  const [statsData, setStatsData] = useState<Stats>(initialStats);
74
  const [loadingStats, setLoadingStats] = useState(false);
 
75
 
76
  // Debounced stats & filters fetch
77
  useEffect(() => {
78
- const qs = new URLSearchParams();
79
- Object.entries(filters).forEach(([key, val]) => {
80
- if (val) qs.set(key, val);
81
- });
82
-
83
- setLoadingStats(true);
84
- // Fetch stats
85
- fetch(`/api/stats?${qs.toString()}`)
86
- .then(res => res.json())
87
- .then((data: Stats) => setStatsData(data))
88
- .catch(console.error)
89
- .finally(() => setLoadingStats(false));
90
-
91
- // Fetch available filters
92
- fetch(`/api/filters?${qs.toString()}`)
93
- .then(res => res.json())
94
- .then((data: AvailableFilters) => setFilters(prev => ({ ...prev, ...{} } as any)))
95
- .catch(console.error);
96
  }, [filters]);
97
 
 
98
  const updateFilter = (key: keyof FilterState) =>
99
  (opt: { value: string } | null) =>
100
  setFilters(prev => ({ ...prev, [key]: opt?.value || "" }));
 
72
  const [orgInput, setOrgInput] = useState("");
73
  const [statsData, setStatsData] = useState<Stats>(initialStats);
74
  const [loadingStats, setLoadingStats] = useState(false);
75
+ const fetchTimer = useRef<number | null>(null);
76
 
77
  // Debounced stats & filters fetch
78
  useEffect(() => {
79
+ if (fetchTimer.current) clearTimeout(fetchTimer.current);
80
+ fetchTimer.current = window.setTimeout(() => {
81
+ const qs = new URLSearchParams();
82
+ Object.entries(filters).forEach(([k, v]) => v && qs.set(k, v));
83
+
84
+ setLoadingStats(true);
85
+ fetch(`/api/stats?${qs.toString()}`)
86
+ .then(r => r.json())
87
+ .then((data: Stats) => setStatsData(data))
88
+ .catch(console.error)
89
+ .finally(() => setLoadingStats(false));
90
+
91
+ }, 300);
92
+ return () => { if (fetchTimer.current) clearTimeout(fetchTimer.current); };
 
 
 
 
93
  }, [filters]);
94
 
95
+
96
  const updateFilter = (key: keyof FilterState) =>
97
  (opt: { value: string } | null) =>
98
  setFilters(prev => ({ ...prev, [key]: opt?.value || "" }));
frontend/src/hooks/useAppState.ts CHANGED
@@ -49,13 +49,13 @@ export const useAppState = () => {
49
  .catch(console.error);
50
  };
51
 
52
- const fetchStats = (filters: FilterState) => {
53
  const params = new URLSearchParams(filters);
54
  fetch(`/api/stats?${params.toString()}`)
55
  .then(res => res.json())
56
  .then((data: Stats) => setStats(data))
57
  .catch(console.error);
58
- };
59
 
60
  const fetchAvailableFilters = (filters: FilterState) => {
61
  const params = new URLSearchParams(filters);
 
49
  .catch(console.error);
50
  };
51
 
52
+ const fetchStats = debounce((filters: FilterState) => {
53
  const params = new URLSearchParams(filters);
54
  fetch(`/api/stats?${params.toString()}`)
55
  .then(res => res.json())
56
  .then((data: Stats) => setStats(data))
57
  .catch(console.error);
58
+ }, 500);
59
 
60
  const fetchAvailableFilters = (filters: FilterState) => {
61
  const params = new URLSearchParams(filters);