bảng tổng hợp thông tin history
This commit is contained in:
parent
1be935a805
commit
a70ad77ae4
|
|
@ -364,6 +364,7 @@ export default function DraggableTabs({
|
||||||
onClose={() => setIsHistoryModalOpen(false)}
|
onClose={() => setIsHistoryModalOpen(false)}
|
||||||
socket={socket}
|
socket={socket}
|
||||||
stationIds={tabs.map((el) => el.id)}
|
stationIds={tabs.map((el) => el.id)}
|
||||||
|
tabs={tabs}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModalConfig
|
<ModalConfig
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import classes from "./Component.module.css";
|
import classes from "./Component.module.css";
|
||||||
import type { Socket } from "socket.io-client";
|
import type { Socket } from "socket.io-client";
|
||||||
|
import type { TStation } from "../untils/types";
|
||||||
|
|
||||||
interface HistoryItem {
|
interface HistoryItem {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -32,6 +33,7 @@ interface ModalHistoryProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
socket: Socket | null;
|
socket: Socket | null;
|
||||||
stationIds?: number[];
|
stationIds?: number[];
|
||||||
|
tabs?: TStation[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const TIME_PERIODS = [
|
const TIME_PERIODS = [
|
||||||
|
|
@ -48,6 +50,7 @@ function ModalHistory({
|
||||||
onClose,
|
onClose,
|
||||||
socket,
|
socket,
|
||||||
stationIds = [],
|
stationIds = [],
|
||||||
|
tabs = [],
|
||||||
}: ModalHistoryProps) {
|
}: ModalHistoryProps) {
|
||||||
const [historyData, setHistoryData] = useState<StationHistory[]>([]);
|
const [historyData, setHistoryData] = useState<StationHistory[]>([]);
|
||||||
const [activeStation, setActiveStation] = useState<string>("");
|
const [activeStation, setActiveStation] = useState<string>("");
|
||||||
|
|
@ -65,10 +68,6 @@ function ModalHistory({
|
||||||
// Listen for history response
|
// Listen for history response
|
||||||
const handleHistoryResponse = (data: StationHistory[]) => {
|
const handleHistoryResponse = (data: StationHistory[]) => {
|
||||||
setHistoryData(data);
|
setHistoryData(data);
|
||||||
// Set first station as active by default only if not already set
|
|
||||||
if (data.length > 0 && !activeStation) {
|
|
||||||
setActiveStation(data[0].stationId.toString());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.on("list_histories", handleHistoryResponse);
|
socket.on("list_histories", handleHistoryResponse);
|
||||||
|
|
@ -76,7 +75,7 @@ function ModalHistory({
|
||||||
return () => {
|
return () => {
|
||||||
socket.off("list_histories", handleHistoryResponse);
|
socket.off("list_histories", handleHistoryResponse);
|
||||||
};
|
};
|
||||||
}, [socket, opened, activeStation]);
|
}, [socket, opened]);
|
||||||
|
|
||||||
// Request history when modal opens
|
// Request history when modal opens
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -87,6 +86,41 @@ function ModalHistory({
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [socket, opened]); // Only re-fetch when modal opens/closes, not when stationIds changes
|
}, [socket, opened]); // Only re-fetch when modal opens/closes, not when stationIds changes
|
||||||
|
|
||||||
|
// Set activeStation from mergedHistoryData when data is available
|
||||||
|
useEffect(() => {
|
||||||
|
if (tabs.length > 0 || historyData.length > 0) {
|
||||||
|
// Create merged data to determine first station
|
||||||
|
const merged: StationHistory[] = [...historyData];
|
||||||
|
tabs.forEach((tab) => {
|
||||||
|
const existingIndex = merged.findIndex((h) => h.stationId === tab.id);
|
||||||
|
if (existingIndex === -1) {
|
||||||
|
merged.push({
|
||||||
|
stationId: tab.id,
|
||||||
|
stationName: tab.name,
|
||||||
|
history: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort by tabs order
|
||||||
|
if (tabs.length > 0) {
|
||||||
|
merged.sort((a, b) => {
|
||||||
|
const aIndex = tabs.findIndex((tab) => tab.id === a.stationId);
|
||||||
|
const bIndex = tabs.findIndex((tab) => tab.id === b.stationId);
|
||||||
|
if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
|
||||||
|
if (aIndex !== -1) return -1;
|
||||||
|
if (bIndex !== -1) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (merged.length > 0 && !activeStation) {
|
||||||
|
setActiveStation(merged[0].stationId.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [historyData.length, tabs.length]);
|
||||||
|
|
||||||
// Reset state when modal closes
|
// Reset state when modal closes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
|
|
@ -223,19 +257,84 @@ function ModalHistory({
|
||||||
return grouped;
|
return grouped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Merge tabs with historyData to ensure all stations from tabs are included
|
||||||
|
// If a station exists in tabs but not in historyData, add it with empty history
|
||||||
|
// Keep all stations from historyData, and add missing stations from tabs
|
||||||
|
// Sort by tabs order if tabs is provided
|
||||||
|
const mergedHistoryData: StationHistory[] = (() => {
|
||||||
|
const result: StationHistory[] = [...historyData];
|
||||||
|
|
||||||
|
if (tabs.length > 0) {
|
||||||
|
tabs.forEach((tab) => {
|
||||||
|
const existingIndex = result.findIndex(
|
||||||
|
(h) => h.stationId === tab.id
|
||||||
|
);
|
||||||
|
if (existingIndex === -1) {
|
||||||
|
// Station from tabs not found in historyData, add it with empty history
|
||||||
|
result.push({
|
||||||
|
stationId: tab.id,
|
||||||
|
stationName: tab.name,
|
||||||
|
history: [],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Update station name from tabs if different
|
||||||
|
result[existingIndex].stationName = tab.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort by tabs order to maintain the same order as tabs
|
||||||
|
result.sort((a, b) => {
|
||||||
|
const aIndex = tabs.findIndex((tab) => tab.id === a.stationId);
|
||||||
|
const bIndex = tabs.findIndex((tab) => tab.id === b.stationId);
|
||||||
|
|
||||||
|
// If both are in tabs, sort by tabs order
|
||||||
|
if (aIndex !== -1 && bIndex !== -1) {
|
||||||
|
return aIndex - bIndex;
|
||||||
|
}
|
||||||
|
// If only a is in tabs, a comes first
|
||||||
|
if (aIndex !== -1) return -1;
|
||||||
|
// If only b is in tabs, b comes first
|
||||||
|
if (bIndex !== -1) return 1;
|
||||||
|
// If neither is in tabs, keep original order
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
|
||||||
// Apply time filter to ALL stations data (không filter bỏ stations không có data)
|
// Apply time filter to ALL stations data (không filter bỏ stations không có data)
|
||||||
const allFilteredStations = historyData.map((station) => ({
|
const allFilteredStations = mergedHistoryData.map((station) => ({
|
||||||
...station,
|
...station,
|
||||||
filteredHistory: filterHistoryByTime(station.history),
|
filteredHistory: filterHistoryByTime(station.history),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Group each station's history by line number
|
// Group each station's history by line number
|
||||||
const allGroupedStations = allFilteredStations.map((station) => ({
|
// Đảm bảo tất cả lines từ tabs đều được hiển thị (kể cả không có data)
|
||||||
...station,
|
const allGroupedStations = allFilteredStations.map((station) => {
|
||||||
groupedHistory: station.filteredHistory.length > 0
|
// Get lines from tabs for this station
|
||||||
|
const tabStation = tabs.find((tab) => tab.id === station.stationId);
|
||||||
|
const tabLines = tabStation?.lines || [];
|
||||||
|
|
||||||
|
// Group filtered history by line number
|
||||||
|
const groupedHistory = station.filteredHistory.length > 0
|
||||||
? groupHistoryByLine(station.filteredHistory)
|
? groupHistoryByLine(station.filteredHistory)
|
||||||
: new Map<number, HistoryItem[]>(),
|
: new Map<number, HistoryItem[]>();
|
||||||
}));
|
|
||||||
|
// Ensure all lines from tabs are included in groupedHistory (even if empty)
|
||||||
|
tabLines.forEach((line) => {
|
||||||
|
const lineNumber = line.lineNumber || line.line_number || line.port;
|
||||||
|
if (lineNumber && !groupedHistory.has(lineNumber)) {
|
||||||
|
// Add empty line group if not exists
|
||||||
|
groupedHistory.set(lineNumber, []);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...station,
|
||||||
|
groupedHistory,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Function to scroll to a specific station (scroll to beginning of content, not header)
|
// Function to scroll to a specific station (scroll to beginning of content, not header)
|
||||||
const scrollToStation = (stationId: number) => {
|
const scrollToStation = (stationId: number) => {
|
||||||
|
|
@ -357,7 +456,7 @@ function ModalHistory({
|
||||||
</Text>
|
</Text>
|
||||||
<ScrollArea h="calc(100% - 30px)">
|
<ScrollArea h="calc(100% - 30px)">
|
||||||
<Flex direction="column" gap="xs">
|
<Flex direction="column" gap="xs">
|
||||||
{historyData.map((station) => (
|
{mergedHistoryData.map((station) => (
|
||||||
<Button
|
<Button
|
||||||
key={station.stationId}
|
key={station.stationId}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|
@ -717,7 +816,7 @@ function ModalHistory({
|
||||||
style={{ height: "calc(75vh - 80px)" }}
|
style={{ height: "calc(75vh - 80px)" }}
|
||||||
>
|
>
|
||||||
<Text c="dimmed" size="lg">
|
<Text c="dimmed" size="lg">
|
||||||
{historyData.length > 0
|
{mergedHistoryData.length > 0
|
||||||
? `No history data available for ${
|
? `No history data available for ${
|
||||||
TIME_PERIODS.find(
|
TIME_PERIODS.find(
|
||||||
(p) => p.value === activeTimePeriod
|
(p) => p.value === activeTimePeriod
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue