Spaces:
Sleeping
Sleeping
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 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
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);
|