185 lines
5.3 KiB
TypeScript
185 lines
5.3 KiB
TypeScript
// src/components/dashboard/RouterTableLogic.tsx
|
|
import { useState, useMemo, useEffect, useCallback } from 'react';
|
|
import { RouterData, FilterType } from '../../types';
|
|
|
|
interface TimeoutInfo {
|
|
timeoutId: NodeJS.Timeout;
|
|
startTime: number;
|
|
}
|
|
|
|
interface AutoHideTimeouts {
|
|
[key: string]: TimeoutInfo;
|
|
}
|
|
|
|
export const useRouterTableLogic = (initialRouters: RouterData[] = []) => {
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
|
|
const [sortConfig, setSortConfig] = useState<{ key: keyof RouterData; direction: 'asc' | 'desc' } | null>(null);
|
|
const [timeLeft, setTimeLeft] = useState<{ [key: string]: number }>({});
|
|
const [autoHideTimeouts, setAutoHideTimeouts] = useState<AutoHideTimeouts>({});
|
|
|
|
const AUTO_HIDE_DELAY = 10000;
|
|
|
|
// Update countdown timer
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
setTimeLeft(prev => {
|
|
const now = Date.now();
|
|
const updated = { ...prev };
|
|
Object.entries(autoHideTimeouts).forEach(([key, info]) => {
|
|
if (info) {
|
|
const remaining = Math.max(0, AUTO_HIDE_DELAY - (now - info.startTime));
|
|
updated[key] = (remaining / AUTO_HIDE_DELAY) * 100;
|
|
}
|
|
});
|
|
return updated;
|
|
});
|
|
}, 100);
|
|
|
|
// Cleanup on unmount
|
|
return () => {
|
|
clearInterval(interval);
|
|
Object.values(autoHideTimeouts).forEach(info => {
|
|
if (info?.timeoutId) {
|
|
clearTimeout(info.timeoutId);
|
|
}
|
|
});
|
|
};
|
|
}, [autoHideTimeouts]);
|
|
|
|
// Filter and sort data
|
|
const filteredRouters = useMemo(() => {
|
|
const routers = Array.isArray(initialRouters) ? initialRouters : [];
|
|
let processed = [...routers];
|
|
|
|
if (searchTerm.trim()) {
|
|
const lowerSearchTerm = searchTerm.toLowerCase().trim();
|
|
processed = processed.filter(router => {
|
|
const searchableFields = ['routerId', 'routerAlias', 'facility'];
|
|
return searchableFields.some(field =>
|
|
String(router[field as keyof RouterData] || '')
|
|
.toLowerCase()
|
|
.includes(lowerSearchTerm)
|
|
);
|
|
});
|
|
}
|
|
|
|
if (sortConfig) {
|
|
processed.sort((a, b) => {
|
|
const aValue = a[sortConfig.key];
|
|
const bValue = b[sortConfig.key];
|
|
|
|
if (aValue < bValue) return sortConfig.direction === 'asc' ? -1 : 1;
|
|
if (aValue > bValue) return sortConfig.direction === 'asc' ? 1 : -1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
return processed;
|
|
}, [initialRouters, searchTerm, sortConfig]);
|
|
|
|
const handleSort = useCallback((key: keyof RouterData) => {
|
|
setSortConfig(current => ({
|
|
key,
|
|
direction: current?.key === key && current.direction === 'asc' ? 'desc' : 'asc'
|
|
}));
|
|
}, []);
|
|
|
|
const toggleRowExpansion = useCallback((rowId: number, section: 'activity' | 'status' | 'disk') => {
|
|
const key = `${rowId}-${section}`;
|
|
|
|
setExpandedRows(prev => {
|
|
const next = new Set(prev);
|
|
|
|
if (next.has(key)) {
|
|
next.delete(key);
|
|
const existingTimeout = autoHideTimeouts[key]?.timeoutId;
|
|
if (existingTimeout) {
|
|
clearTimeout(existingTimeout);
|
|
setAutoHideTimeouts(prev => {
|
|
const next = { ...prev };
|
|
delete next[key];
|
|
return next;
|
|
});
|
|
setTimeLeft(prev => {
|
|
const next = { ...prev };
|
|
delete next[key];
|
|
return next;
|
|
});
|
|
}
|
|
} else {
|
|
next.add(key);
|
|
const timeoutId = setTimeout(() => {
|
|
setExpandedRows(prev => {
|
|
const next = new Set(prev);
|
|
next.delete(key);
|
|
return next;
|
|
});
|
|
setAutoHideTimeouts(prev => {
|
|
const next = { ...prev };
|
|
delete next[key];
|
|
return next;
|
|
});
|
|
setTimeLeft(prev => {
|
|
const next = { ...prev };
|
|
delete next[key];
|
|
return next;
|
|
});
|
|
}, AUTO_HIDE_DELAY);
|
|
|
|
setAutoHideTimeouts(prev => ({
|
|
...prev,
|
|
[key]: { timeoutId, startTime: Date.now() }
|
|
}));
|
|
setTimeLeft(prev => ({ ...prev, [key]: 100 }));
|
|
}
|
|
|
|
return next;
|
|
});
|
|
}, [autoHideTimeouts]);
|
|
|
|
const handleExpandedContentHover = useCallback((rowId: number, section: 'activity' | 'status' | 'disk') => {
|
|
const key = `${rowId}-${section}`;
|
|
const existingTimeout = autoHideTimeouts[key]?.timeoutId;
|
|
|
|
if (existingTimeout) {
|
|
clearTimeout(existingTimeout);
|
|
|
|
const timeoutId = setTimeout(() => {
|
|
setExpandedRows(prev => {
|
|
const next = new Set(prev);
|
|
next.delete(key);
|
|
return next;
|
|
});
|
|
setAutoHideTimeouts(prev => {
|
|
const next = { ...prev };
|
|
delete next[key];
|
|
return next;
|
|
});
|
|
setTimeLeft(prev => {
|
|
const next = { ...prev };
|
|
delete next[key];
|
|
return next;
|
|
});
|
|
}, AUTO_HIDE_DELAY);
|
|
|
|
setAutoHideTimeouts(prev => ({
|
|
...prev,
|
|
[key]: { timeoutId, startTime: Date.now() }
|
|
}));
|
|
setTimeLeft(prev => ({ ...prev, [key]: 100 }));
|
|
}
|
|
}, [autoHideTimeouts]);
|
|
|
|
return {
|
|
routers: filteredRouters,
|
|
totalRouters: initialRouters.length,
|
|
searchTerm,
|
|
setSearchTerm,
|
|
expandedRows,
|
|
timeLeft,
|
|
handleSort,
|
|
toggleRowExpansion,
|
|
handleExpandedContentHover
|
|
};
|
|
}; |