import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Box, Typography, Button, Paper } from '@mui/material'; import { activityFeedsService } from '../../api/activityFeedsService'; import { TopFilterBar } from '../../components/common/TopFilterBar'; import { useFeedStore } from '../../store/feedStore'; export const Dashboard: React.FC = () => { const { selectedSite, auditStatus, filterFromDate, filterTillDate, filterMinChainage, filterMaxChainage, selectedAssetIds, dashboardCache, setDashboardCache, searchAnomalyId, filterPlaza, isRectificationEnabled, tabs, selectedTabIndex } = useFeedStore(); const navigate = useNavigate(); const selectedSiteId = selectedSite?.site_id ?? ''; const assetIdsKey = selectedAssetIds.join(','); const activeTab = tabs[selectedTabIndex] || { date: '', isRectificationTab: false }; const activeDate = activeTab.date || ''; const isRectActive = isRectificationEnabled || activeTab.isRectificationTab; // Build a key that uniquely identifies the current filter state const currentFilterKey = `${selectedSiteId}|${auditStatus}|${filterFromDate}|${filterTillDate}|${assetIdsKey}|${filterMinChainage}|${filterMaxChainage}|${searchAnomalyId}|${filterPlaza}|${isRectActive}|${activeDate}`; // Initialise stats from cache immediately (no flicker on tab switch) const [stats, setStats] = useState(() => dashboardCache.stats ?? { globalTotal: 0, batchTotal: 0, batchAudited: 0, batchPending: 0, batchAnomaliesFound: 0, firstPendingIndex: -1, } ); // Only show loading spinner if there's no cached result for these filters const [loading, setLoading] = useState(dashboardCache.stats === null); useEffect(() => { // CACHE HIT: filters unchanged since last fetch — skip API call entirely if (dashboardCache.stats !== null && currentFilterKey === `${dashboardCache.siteId}|${dashboardCache.auditStatus}|${dashboardCache.fromDate}|${dashboardCache.tillDate}|${dashboardCache.assetIds}|${dashboardCache.minChainage}|${dashboardCache.maxChainage}|${dashboardCache.searchAnomalyId}|${dashboardCache.filterPlaza}|${dashboardCache.isRectificationEnabled ?? false}|${dashboardCache.date ?? ''}`) { setStats(dashboardCache.stats); setLoading(false); return; } const fetchStats = async () => { try { setLoading(true); const res: any = await activityFeedsService.getHistory({ date: activeDate, pageNo: 0, pageSize: 200, sortByDateAsc: false, isRectificationEnabled: isRectActive, auditStatus: auditStatus, isTrueFalse: isRectActive ? 'both' : (auditStatus === 'False Audits' ? 'true' : 'both'), auto_audit: isRectActive ? '' : (auditStatus === 'Auto Audits' ? 'true' : (auditStatus === 'Manual' ? 'false' : '')), siteIds: (!selectedSiteId || selectedSiteId === 'All Sites') ? '' : selectedSiteId, assetsIds: assetIdsKey, fromDate: filterFromDate, tillDate: filterTillDate, fromChainage: filterMinChainage, toChainage: filterMaxChainage, anomalyIds: searchAnomalyId, plaza: filterPlaza, }); if (res) { const anomalies = res.anomalies || []; const newStats = { globalTotal: res.count || anomalies.length, batchTotal: anomalies.length, batchAudited: anomalies.filter((a: any) => a.IsAudited === 1).length, batchPending: anomalies.filter((a: any) => a.IsAudited === 0).length, batchAnomaliesFound: anomalies.filter((a: any) => a.Audit_status === 1).length, firstPendingIndex: anomalies.findIndex((a: any) => a.IsAudited === 0) }; setStats(newStats); // Persist to store cache so re-mounting the Dashboard skips this fetch setDashboardCache({ siteId: selectedSiteId, auditStatus, fromDate: filterFromDate, tillDate: filterTillDate, assetIds: assetIdsKey, minChainage: filterMinChainage, maxChainage: filterMaxChainage, searchAnomalyId, filterPlaza, isRectificationEnabled: isRectActive, date: activeDate, stats: newStats, }); } } catch (err) { console.error('Failed to load dashboard stats', err); } finally { setLoading(false); } }; fetchStats(); }, [currentFilterKey]); // eslint-disable-line react-hooks/exhaustive-deps return ( {/* Stats Row */} {/* Active Batch */} Active Batch {loading ? '...' : stats.batchTotal.toLocaleString()} of {loading ? '...' : stats.globalTotal.toLocaleString()} total items on site {/* Audited */} Audited {loading ? '...' : stats.batchAudited.toLocaleString()} in current batch {/* Pending */} Pending {loading ? '...' : stats.batchPending.toLocaleString()} in current batch {/* Anomalies Found */} Anomalies Found {loading ? '...' : stats.batchAnomaliesFound.toLocaleString()} in current batch {/* Start Button */} {/* Footer */} Keyboard shortcuts available inside the audit view ); };