Refactor ModalHistory time filtering and UI
Adjusted time period logic in ModalHistory to use correct time ranges for filtering history data. Improved code formatting, grouping, and UI rendering for station history. Added validation in backend addHistory to ensure pid and sn are present before saving history items.
This commit is contained in:
parent
6f8aa1d69b
commit
2ba35743fd
|
|
@ -696,6 +696,7 @@ export default class LineConnection {
|
|||
}
|
||||
|
||||
async addHistory(stationId: number, lineId: number, item: HistoryItem) {
|
||||
if (!item.pid || !item.sn) return
|
||||
const key = `station:${stationId}:line:${lineId}:history`
|
||||
const now = Date.now()
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,12 @@ const TIME_PERIODS = [
|
|||
{ label: "last 48h", value: "last_48h" },
|
||||
];
|
||||
|
||||
function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistoryProps) {
|
||||
function ModalHistory({
|
||||
opened,
|
||||
onClose,
|
||||
socket,
|
||||
stationIds = [],
|
||||
}: ModalHistoryProps) {
|
||||
const [historyData, setHistoryData] = useState<StationHistory[]>([]);
|
||||
const [activeStation, setActiveStation] = useState<string>("");
|
||||
const [activeTimePeriod, setActiveTimePeriod] = useState<string>("current");
|
||||
|
|
@ -71,7 +76,7 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
// Request history when modal opens
|
||||
useEffect(() => {
|
||||
if (!socket || !opened) return;
|
||||
|
||||
|
||||
// Request history with station IDs
|
||||
socket.emit("get_list_history", { stationIds });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -86,7 +91,6 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
}
|
||||
}, [opened]);
|
||||
|
||||
|
||||
// Utility function to format timestamp (can be used later if needed)
|
||||
// const formatTimestamp = (timestamp: number) => {
|
||||
// const date = new Date(timestamp);
|
||||
|
|
@ -97,23 +101,23 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
const getTimeRange = (period: string): [number, number] => {
|
||||
const now = Date.now();
|
||||
const HOUR = 60 * 60 * 1000;
|
||||
|
||||
|
||||
switch (period) {
|
||||
case "current":
|
||||
// Current: chỉ hiện tại (4h gần nhất)
|
||||
return [now - 4 * HOUR, now];
|
||||
return [0, now];
|
||||
case "last_4h":
|
||||
// Last 4h: bao gồm current + last 4h (0-8h)
|
||||
return [now - 8 * HOUR, now];
|
||||
return [now - 4 * HOUR, now];
|
||||
case "last_8h":
|
||||
// Last 8h: bao gồm current + last 4h + last 8h (0-24h)
|
||||
return [now - 24 * HOUR, now];
|
||||
return [now - 8 * HOUR, now];
|
||||
case "last_24h":
|
||||
// Last 24h: bao gồm current + last 4h + last 8h + last 24h (0-48h)
|
||||
return [now - 48 * HOUR, now];
|
||||
return [now - 24 * HOUR, now];
|
||||
case "last_48h":
|
||||
// Last 48h: tất cả data (từ đầu đến giờ)
|
||||
return [0, now];
|
||||
return [now - 48 * HOUR, now];
|
||||
default:
|
||||
return [0, now];
|
||||
}
|
||||
|
|
@ -122,27 +126,29 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
// Filter history based on time period
|
||||
const filterHistoryByTime = (history: HistoryItem[]): HistoryItem[] => {
|
||||
const [startTime, endTime] = getTimeRange(activeTimePeriod);
|
||||
return history.filter((item) =>
|
||||
item.timestamp >= startTime && item.timestamp < endTime
|
||||
return history.filter(
|
||||
(item) => item.timestamp >= startTime && item.timestamp < endTime
|
||||
);
|
||||
};
|
||||
|
||||
// Group history items by line number
|
||||
const groupHistoryByLine = (history: HistoryItem[]): Map<number, HistoryItem[]> => {
|
||||
const groupHistoryByLine = (
|
||||
history: HistoryItem[]
|
||||
): Map<number, HistoryItem[]> => {
|
||||
const grouped = new Map<number, HistoryItem[]>();
|
||||
|
||||
|
||||
history.forEach((item) => {
|
||||
if (!grouped.has(item.number)) {
|
||||
grouped.set(item.number, []);
|
||||
}
|
||||
grouped.get(item.number)!.push(item);
|
||||
});
|
||||
|
||||
|
||||
// Sort items within each group by timestamp (newest first)
|
||||
grouped.forEach((items) => {
|
||||
items.sort((a, b) => b.timestamp - a.timestamp);
|
||||
});
|
||||
|
||||
|
||||
return grouped;
|
||||
};
|
||||
|
||||
|
|
@ -154,7 +160,7 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
const filteredHistory = currentStationData
|
||||
? filterHistoryByTime(currentStationData.history)
|
||||
: [];
|
||||
|
||||
|
||||
// Group filtered history by line number
|
||||
const groupedHistory = groupHistoryByLine(filteredHistory);
|
||||
|
||||
|
|
@ -214,8 +220,8 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
<div
|
||||
style={{
|
||||
padding: "20px",
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden",
|
||||
// overflowY: "auto",
|
||||
// overflowX: "hidden",
|
||||
flex: 1,
|
||||
}}
|
||||
className={classes.hideScrollBar}
|
||||
|
|
@ -231,7 +237,7 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
}}
|
||||
>
|
||||
<Text fw={600} size="sm" mb="xs" c="dimmed">
|
||||
HISTORY
|
||||
List stations
|
||||
</Text>
|
||||
<ScrollArea h="calc(100% - 30px)">
|
||||
<Flex direction="column" gap="xs">
|
||||
|
|
@ -284,11 +290,15 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
backgroundColor: "white",
|
||||
}}
|
||||
>
|
||||
<ScrollArea
|
||||
<ScrollArea
|
||||
h="calc(75vh - 80px)"
|
||||
viewportRef={scrollViewportRef}
|
||||
onScrollPositionChange={(position) => {
|
||||
if (!scrollViewportRef.current || isAutoSwitchingRef.current) return;
|
||||
if (
|
||||
!scrollViewportRef.current ||
|
||||
isAutoSwitchingRef.current
|
||||
)
|
||||
return;
|
||||
|
||||
const scrollTop = position.y;
|
||||
const target = scrollViewportRef.current;
|
||||
|
|
@ -296,19 +306,28 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
const clientHeight = target.clientHeight;
|
||||
|
||||
// Check if scrolled to bottom
|
||||
const isAtBottom = Math.abs(scrollTop + clientHeight - scrollHeight) < 5;
|
||||
const isAtBottom =
|
||||
Math.abs(scrollTop + clientHeight - scrollHeight) < 5;
|
||||
|
||||
if (isAtBottom && historyData.length > 0) {
|
||||
isAutoSwitchingRef.current = true;
|
||||
|
||||
const currentStationIndex = historyData.findIndex(
|
||||
(station) => station.stationId.toString() === activeStation
|
||||
(station) =>
|
||||
station.stationId.toString() === activeStation
|
||||
);
|
||||
|
||||
if (currentStationIndex !== -1 && currentStationIndex < historyData.length - 1) {
|
||||
if (
|
||||
currentStationIndex !== -1 &&
|
||||
currentStationIndex < historyData.length - 1
|
||||
) {
|
||||
// Chuyển sang station tiếp theo
|
||||
setActiveStation(historyData[currentStationIndex + 1].stationId.toString());
|
||||
|
||||
setActiveStation(
|
||||
historyData[
|
||||
currentStationIndex + 1
|
||||
].stationId.toString()
|
||||
);
|
||||
|
||||
// Reset scroll to top
|
||||
setTimeout(() => {
|
||||
if (scrollViewportRef.current) {
|
||||
|
|
@ -330,52 +349,73 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
{Array.from(groupedHistory.entries())
|
||||
.sort(([lineA], [lineB]) => lineA - lineB)
|
||||
.map(([lineNumber, items]) => (
|
||||
<Box
|
||||
key={`line-group-${lineNumber}`}
|
||||
style={{
|
||||
marginBottom: "8px",
|
||||
border: "1px solid #dee2e6",
|
||||
borderRadius: "4px",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{/* Header của nhóm - hiển thị line number */}
|
||||
<Box
|
||||
key={`line-group-${lineNumber}`}
|
||||
style={{
|
||||
padding: "8px 16px",
|
||||
backgroundColor: "#e9ecef",
|
||||
fontWeight: 600,
|
||||
marginBottom: "8px",
|
||||
border: "1px solid #dee2e6",
|
||||
borderRadius: "4px",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<Text size="sm" fw={600}>
|
||||
Line {lineNumber} ({items.length} {items.length > 1 ? 'records' : 'record'})
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Các items trong nhóm */}
|
||||
{items.map((item, itemIndex) => (
|
||||
{/* Header của nhóm - hiển thị line number */}
|
||||
<Box
|
||||
key={`${item.stationId}-${item.number}-${item.timestamp}-${itemIndex}`}
|
||||
style={{
|
||||
padding: "8px 16px 8px 32px", // Tăng padding-left lên 32px
|
||||
borderTop: itemIndex > 0 ? "1px solid #f1f3f5" : "none",
|
||||
backgroundColor: itemIndex % 2 === 0 ? "white" : "#f8f9fa",
|
||||
padding: "8px 16px",
|
||||
backgroundColor: "#e9ecef",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
<Text size="sm" style={{ fontFamily: "monospace" }}>
|
||||
{item.pid} {item.vid} SN: {item.sn}
|
||||
<span style={{ marginLeft: "20px", color: "#868e96" }}>
|
||||
| {item.scenario}
|
||||
</span>
|
||||
<span style={{ marginLeft: "10px", color: "#adb5bd", fontSize: "11px" }}>
|
||||
{new Date(item.timestamp).toLocaleString()}
|
||||
</span>
|
||||
<Text size="sm" fw={600}>
|
||||
Line {lineNumber} ({items.length}{" "}
|
||||
{items.length > 1 ? "records" : "record"})
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
))}
|
||||
|
||||
|
||||
{/* Các items trong nhóm */}
|
||||
{items.map((item, itemIndex) => (
|
||||
<Box
|
||||
key={`${item.stationId}-${item.number}-${item.timestamp}-${itemIndex}`}
|
||||
style={{
|
||||
padding: "8px 16px 8px 32px", // Tăng padding-left lên 32px
|
||||
borderTop:
|
||||
itemIndex > 0
|
||||
? "1px solid #f1f3f5"
|
||||
: "none",
|
||||
backgroundColor:
|
||||
itemIndex % 2 === 0 ? "white" : "#f8f9fa",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
size="sm"
|
||||
style={{ fontFamily: "monospace" }}
|
||||
>
|
||||
{item.pid} {item.vid} SN: {item.sn}
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "20px",
|
||||
color: "#868e96",
|
||||
}}
|
||||
>
|
||||
| {item.scenario}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
color: "#adb5bd",
|
||||
fontSize: "11px",
|
||||
}}
|
||||
>
|
||||
{new Date(
|
||||
item.timestamp
|
||||
).toLocaleString()}
|
||||
</span>
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
))}
|
||||
|
||||
{/* Spacer để đảm bảo có thể scroll ngay cả khi content ít */}
|
||||
<Box style={{ height: "200px" }} />
|
||||
</>
|
||||
|
|
@ -383,11 +423,15 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
<Flex
|
||||
align="center"
|
||||
justify="center"
|
||||
style={{ minHeight: "calc(75vh - 80px)" }}
|
||||
style={{ height: "calc(75vh - 80px)" }}
|
||||
>
|
||||
<Text c="dimmed" size="lg">
|
||||
{currentStationData
|
||||
? `No history data available for ${TIME_PERIODS.find((p) => p.value === activeTimePeriod)?.label}`
|
||||
? `No history data available for ${
|
||||
TIME_PERIODS.find(
|
||||
(p) => p.value === activeTimePeriod
|
||||
)?.label
|
||||
}`
|
||||
: "No history data available"}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
|
@ -404,4 +448,3 @@ function ModalHistory({ opened, onClose, socket, stationIds = [] }: ModalHistory
|
|||
}
|
||||
|
||||
export default ModalHistory;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue