From 6e63b49a4c3ed5fd76784e49e21a6a493dc6a913 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 11 Feb 2026 15:01:59 +0800 Subject: [PATCH] Clean ovewview code --- web/pages/Dashboard.tsx | 72 ++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/web/pages/Dashboard.tsx b/web/pages/Dashboard.tsx index 6f77690..4990bf8 100644 --- a/web/pages/Dashboard.tsx +++ b/web/pages/Dashboard.tsx @@ -1,7 +1,7 @@ import React, { useState, useMemo, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Phone, CheckCircle, Clock, UserCheck, Activity, Filter, ChevronDown, BarChart3, HelpCircle, Mail, Sparkles, ArrowDown, Bot, Zap, Rocket, LineChart, Layers, Fingerprint, Network, MonitorPlay, Plus } from 'lucide-react'; +import { Phone, CheckCircle, Clock, UserCheck, ChevronDown, BarChart3, HelpCircle, Mail, ArrowDown, Bot, Zap, Rocket, LineChart, Layers, Fingerprint, Network, MonitorPlay, Plus } from 'lucide-react'; import { Card, Button } from '../components/UI'; import { getDashboardStats } from '../services/mockData'; import { Assistant } from '../types'; @@ -27,45 +27,78 @@ export const DashboardPage: React.FC = () => { }, [timeRange, selectedAssistantId]); useEffect(() => { + let disposed = false; + const loadAssistants = async () => { try { const list = await fetchAssistants(); - setAssistants(list); + if (!disposed) { + setAssistants(list); + } } catch (error) { - console.error(error); + if (!disposed) { + console.error(error); + } } }; + loadAssistants(); + + return () => { + disposed = true; + }; }, []); useEffect(() => { const updateTopRailHeight = () => { - setTopRailHeight(topRailRef.current?.offsetHeight ?? 0); + const nextHeight = topRailRef.current?.offsetHeight ?? 0; + setTopRailHeight((prev) => (prev === nextHeight ? prev : nextHeight)); }; updateTopRailHeight(); - const observer = new ResizeObserver(() => { - updateTopRailHeight(); - }); - - if (topRailRef.current) { + let observer: ResizeObserver | null = null; + if (typeof ResizeObserver !== 'undefined' && topRailRef.current) { + observer = new ResizeObserver(() => { + updateTopRailHeight(); + }); observer.observe(topRailRef.current); } window.addEventListener('resize', updateTopRailHeight); return () => { - observer.disconnect(); + if (observer) { + observer.disconnect(); + } window.removeEventListener('resize', updateTopRailHeight); }; }, []); useEffect(() => { if (!scrollRootRef.current || !overviewRef.current) return; + if (typeof IntersectionObserver === 'undefined') { + const onScroll = () => { + if (!scrollRootRef.current || !overviewRef.current) return; + const rootRect = scrollRootRef.current.getBoundingClientRect(); + const overviewRect = overviewRef.current.getBoundingClientRect(); + const lowerBound = rootRect.top + rootRect.height * 0.35; + const upperBound = rootRect.bottom - rootRect.height * 0.35; + const isVisible = overviewRect.bottom > lowerBound && overviewRect.top < upperBound; + setIsOverviewVisible((prev) => (prev === isVisible ? prev : isVisible)); + }; + + onScroll(); + scrollRootRef.current.addEventListener('scroll', onScroll, { passive: true }); + window.addEventListener('resize', onScroll); + return () => { + scrollRootRef.current?.removeEventListener('scroll', onScroll); + window.removeEventListener('resize', onScroll); + }; + } const observer = new IntersectionObserver( ([entry]) => { - setIsOverviewVisible(entry.isIntersecting); + setIsOverviewVisible((prev) => (prev === entry.isIntersecting ? prev : entry.isIntersecting)); }, { root: scrollRootRef.current, @@ -81,22 +114,25 @@ export const DashboardPage: React.FC = () => { const updateScrollRootCenter = () => { if (!scrollRootRef.current) return; const rect = scrollRootRef.current.getBoundingClientRect(); - setScrollRootCenterX(rect.left + rect.width / 2); + const nextCenterX = rect.left + rect.width / 2; + setScrollRootCenterX((prev) => (prev === nextCenterX ? prev : nextCenterX)); }; updateScrollRootCenter(); - const observer = new ResizeObserver(() => { - updateScrollRootCenter(); - }); - - if (scrollRootRef.current) { + let observer: ResizeObserver | null = null; + if (typeof ResizeObserver !== 'undefined' && scrollRootRef.current) { + observer = new ResizeObserver(() => { + updateScrollRootCenter(); + }); observer.observe(scrollRootRef.current); } window.addEventListener('resize', updateScrollRootCenter); return () => { - observer.disconnect(); + if (observer) { + observer.disconnect(); + } window.removeEventListener('resize', updateScrollRootCenter); }; }, []);