Fix scroll danh sách cuối station
This commit is contained in:
parent
c532e78093
commit
1be935a805
|
|
@ -56,6 +56,8 @@ function ModalHistory({
|
|||
const stationRefs = useRef<Map<number, HTMLDivElement>>(new Map());
|
||||
const stationContentRefs = useRef<Map<number, HTMLDivElement>>(new Map());
|
||||
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const lastScrollTopRef = useRef<number>(0);
|
||||
const isBlockingScrollRef = useRef<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket || !opened) return;
|
||||
|
|
@ -93,6 +95,8 @@ function ModalHistory({
|
|||
setActiveTimePeriod("current");
|
||||
stationRefs.current.clear();
|
||||
stationContentRefs.current.clear();
|
||||
isBlockingScrollRef.current = false;
|
||||
lastScrollTopRef.current = 0;
|
||||
}
|
||||
|
||||
return () => {
|
||||
|
|
@ -102,6 +106,42 @@ function ModalHistory({
|
|||
};
|
||||
}, [opened]);
|
||||
|
||||
// Prevent wheel scroll when at last station with no data
|
||||
useEffect(() => {
|
||||
if (!scrollViewportRef.current || !opened) return;
|
||||
|
||||
const scrollContainer = scrollViewportRef.current;
|
||||
|
||||
const handleWheel = (e: WheelEvent) => {
|
||||
if (!isBlockingScrollRef.current) return;
|
||||
|
||||
const scrollHeight = scrollContainer.scrollHeight;
|
||||
const clientHeight = scrollContainer.clientHeight;
|
||||
const currentScrollTop = scrollContainer.scrollTop;
|
||||
const maxScrollTop = scrollHeight - clientHeight;
|
||||
const isAtBottom = Math.abs(currentScrollTop + clientHeight - scrollHeight) < 20;
|
||||
|
||||
// If at bottom and trying to scroll down, prevent it
|
||||
if (isAtBottom && e.deltaY > 0) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// Ensure we stay at bottom
|
||||
if (currentScrollTop < maxScrollTop - 5) {
|
||||
scrollContainer.scrollTo({
|
||||
top: maxScrollTop,
|
||||
behavior: "auto",
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scrollContainer.addEventListener("wheel", handleWheel, { passive: false });
|
||||
|
||||
return () => {
|
||||
scrollContainer.removeEventListener("wheel", handleWheel);
|
||||
};
|
||||
}, [opened, historyData, activeTimePeriod, activeStation]);
|
||||
|
||||
// Scroll to station when activeStation changes (only when clicked, not when auto-detected)
|
||||
const isManualScrollRef = useRef(false);
|
||||
|
||||
|
|
@ -386,6 +426,88 @@ function ModalHistory({
|
|||
const containerRect = scrollContainer.getBoundingClientRect();
|
||||
const topThreshold = containerRect.top + 10; // Sát top với threshold 10px
|
||||
|
||||
// Check if scrolled to bottom
|
||||
const scrollHeight = scrollContainer.scrollHeight;
|
||||
const clientHeight = scrollContainer.clientHeight;
|
||||
const currentScrollTop = scrollContainer.scrollTop;
|
||||
const isAtBottom = Math.abs(currentScrollTop + clientHeight - scrollHeight) < 20;
|
||||
|
||||
// Check if currently at last station with no data - prevent scrolling
|
||||
if (allGroupedStations.length > 0) {
|
||||
const lastStation = allGroupedStations[allGroupedStations.length - 1];
|
||||
const lastStationHasNoData = lastStation.groupedHistory.size === 0;
|
||||
const lastStationIdStr = String(lastStation.stationId);
|
||||
|
||||
// If at bottom and last station has no data, prevent scrolling
|
||||
if (isAtBottom && lastStationHasNoData) {
|
||||
if (lastStationIdStr !== activeStation) {
|
||||
setActiveStation(lastStationIdStr);
|
||||
}
|
||||
|
||||
// Block scroll if trying to scroll down
|
||||
isBlockingScrollRef.current = true;
|
||||
const maxScrollTop = scrollHeight - clientHeight;
|
||||
|
||||
// If trying to scroll down (scrollTop increased), reset to bottom
|
||||
if (currentScrollTop > lastScrollTopRef.current && currentScrollTop < maxScrollTop - 5) {
|
||||
scrollContainer.scrollTo({
|
||||
top: maxScrollTop,
|
||||
behavior: "auto", // Use auto for instant reset
|
||||
});
|
||||
lastScrollTopRef.current = maxScrollTop;
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep scroll at bottom
|
||||
lastScrollTopRef.current = maxScrollTop;
|
||||
return;
|
||||
}
|
||||
|
||||
// If currently viewing last station with no data
|
||||
const currentStation = allGroupedStations.find(
|
||||
(s) => s.stationId.toString() === activeStation
|
||||
);
|
||||
const isLastStation = currentStation?.stationId === lastStation.stationId;
|
||||
const hasNoData = currentStation?.groupedHistory.size === 0;
|
||||
|
||||
if (isLastStation && hasNoData) {
|
||||
isBlockingScrollRef.current = true;
|
||||
const maxScrollTop = scrollHeight - clientHeight;
|
||||
|
||||
// If trying to scroll down past bottom, reset to bottom
|
||||
if (currentScrollTop > lastScrollTopRef.current && currentScrollTop < maxScrollTop - 5) {
|
||||
scrollContainer.scrollTo({
|
||||
top: maxScrollTop,
|
||||
behavior: "auto",
|
||||
});
|
||||
lastScrollTopRef.current = maxScrollTop;
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep scroll at bottom if already there
|
||||
if (isAtBottom) {
|
||||
lastScrollTopRef.current = maxScrollTop;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
isBlockingScrollRef.current = false;
|
||||
}
|
||||
} else {
|
||||
isBlockingScrollRef.current = false;
|
||||
}
|
||||
|
||||
// Update last scroll position
|
||||
lastScrollTopRef.current = currentScrollTop;
|
||||
|
||||
// If at bottom, select the last station
|
||||
if (isAtBottom && allGroupedStations.length > 0) {
|
||||
const lastStation = allGroupedStations[allGroupedStations.length - 1];
|
||||
const lastStationIdStr = String(lastStation.stationId);
|
||||
if (lastStationIdStr !== activeStation) {
|
||||
setActiveStation(lastStationIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Find which station header is closest to top
|
||||
// Ưu tiên: header đã vượt qua top threshold (ở trên) > header chưa đến (ở dưới)
|
||||
type StationInfo = { id: number; distance: number; isAbove: boolean };
|
||||
|
|
@ -427,7 +549,13 @@ function ModalHistory({
|
|||
{allGroupedStations.length > 0 ? (
|
||||
<>
|
||||
{allGroupedStations.map((station) => (
|
||||
<Box key={`station-${station.stationId}`} style={{ marginBottom: "24px" }}>
|
||||
<Box
|
||||
key={`station-${station.stationId}`}
|
||||
style={{
|
||||
marginBottom: "24px",
|
||||
minHeight: station.groupedHistory.size === 0 ? "200px" : "auto" // Đảm bảo station không có content vẫn có height
|
||||
}}
|
||||
>
|
||||
{/* Station Title */}
|
||||
<Box
|
||||
ref={(el) => {
|
||||
|
|
@ -579,8 +707,8 @@ function ModalHistory({
|
|||
</Box>
|
||||
))}
|
||||
|
||||
{/* Spacer để đảm bảo có thể scroll ngay cả khi content ít */}
|
||||
<Box style={{ height: "700px" }} />
|
||||
{/* Spacer để đảm bảo có thể scroll đến tất cả stations, kể cả cuối cùng */}
|
||||
<Box style={{ height: "1000px" }} />
|
||||
</>
|
||||
) : (
|
||||
<Flex
|
||||
|
|
|
|||
Loading…
Reference in New Issue