Reverse feed direction and add navigation arrows

This commit is contained in:
2025-01-04 00:51:18 -05:00
parent 194ac96732
commit 1b797eecaf

View File

@@ -18,11 +18,14 @@ import {
Activity, Activity,
AlertCircle, AlertCircle,
FileText, FileText,
ChevronLeft,
ChevronRight,
} from "lucide-react"; } from "lucide-react";
import { format } from "date-fns"; import { format } from "date-fns";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { EventDialog } from "./EventFeed.jsx"; import { EventDialog } from "./EventFeed.jsx";
import { Button } from "@/components/ui/button";
const METRIC_IDS = { const METRIC_IDS = {
PLACED_ORDER: "Y8cqcF", PLACED_ORDER: "Y8cqcF",
@@ -319,6 +322,34 @@ const MiniEventFeed = ({
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [lastUpdate, setLastUpdate] = useState(null); const [lastUpdate, setLastUpdate] = useState(null);
const scrollRef = useRef(null); const scrollRef = useRef(null);
const [showLeftArrow, setShowLeftArrow] = useState(false);
const [showRightArrow, setShowRightArrow] = useState(false);
const handleScroll = () => {
if (scrollRef.current) {
const { scrollLeft, scrollWidth, clientWidth } = scrollRef.current;
setShowLeftArrow(scrollLeft > 0);
setShowRightArrow(scrollLeft < scrollWidth - clientWidth - 1);
}
};
const scrollToEnd = () => {
if (scrollRef.current) {
scrollRef.current.scrollTo({
left: scrollRef.current.scrollWidth,
behavior: 'smooth'
});
}
};
const scrollToStart = () => {
if (scrollRef.current) {
scrollRef.current.scrollTo({
left: 0,
behavior: 'smooth'
});
}
};
const fetchEvents = useCallback(async () => { const fetchEvents = useCallback(async () => {
try { try {
@@ -354,6 +385,7 @@ const MiniEventFeed = ({
left: scrollRef.current.scrollWidth, left: scrollRef.current.scrollWidth,
behavior: 'instant' behavior: 'instant'
}); });
handleScroll();
}, 0); }, 0);
} }
} catch (error) { } catch (error) {
@@ -370,37 +402,63 @@ const MiniEventFeed = ({
return () => clearInterval(interval); return () => clearInterval(interval);
}, [fetchEvents]); }, [fetchEvents]);
useEffect(() => {
handleScroll();
}, [events]);
return ( return (
<div className="fixed bottom-0 left-0 right-0"> <div className="fixed bottom-0 left-0 right-0">
<Card className="bg-gradient-to-br rounded-none from-gray-900 to-gray-600 backdrop-blur"> <Card className="bg-gradient-to-br rounded-none from-gray-900 to-gray-600 backdrop-blur">
<div className="px-1 pt-2 pb-3"> <div className="px-1 pt-2 pb-3 relative">
<div className="overflow-x-auto overflow-y-hidden [&::-webkit-scrollbar]:hidden [-ms-overflow-style:'none'] [scrollbar-width:'none']"> {showLeftArrow && (
<div className="flex flex-row gap-3 pr-4" style={{ width: 'max-content' }}> <Button
{loading && !events.length ? ( variant="ghost"
<LoadingState /> className="absolute left-0 top-1/2 -translate-y-1/2 z-10 bg-gray-900/50 hover:bg-gray-900/75 h-12 w-8 p-0 [&_svg]:!h-8 [&_svg]:!w-8"
) : error ? ( onClick={scrollToStart}
<Alert variant="destructive" className="mx-4"> >
<AlertCircle className="h-4 w-4" /> <ChevronLeft className="text-white" />
<AlertTitle>Error</AlertTitle> </Button>
<AlertDescription> )}
Failed to load event feed: {error} {showRightArrow && (
</AlertDescription> <Button
</Alert> variant="ghost"
) : !events || events.length === 0 ? ( className="absolute right-0 top-1/2 -translate-y-1/2 z-10 bg-gray-900/50 hover:bg-gray-900/75 h-12 w-8 p-0 [&_svg]:!h-8 [&_svg]:!w-8"
<div className="px-4"> onClick={scrollToEnd}
<EmptyState /> >
</div> <ChevronRight className="text-white" />
) : ( </Button>
events.map((event) => ( )}
<EventCard <div
key={event.id} ref={scrollRef}
event={event} onScroll={handleScroll}
/> className="overflow-x-auto overflow-y-hidden [&::-webkit-scrollbar]:hidden [-ms-overflow-style:'none'] [scrollbar-width:'none']"
)) >
)} <div className="flex flex-row gap-3 pr-4" style={{ width: 'max-content' }}>
{loading && !events.length ? (
<LoadingState />
) : error ? (
<Alert variant="destructive" className="mx-4">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>
Failed to load event feed: {error}
</AlertDescription>
</Alert>
) : !events || events.length === 0 ? (
<div className="px-4">
<EmptyState />
</div>
) : (
[...events].reverse().map((event) => (
<EventCard
key={event.id}
event={event}
/>
))
)}
</div>
</div> </div>
</div> </div>
</div>
</Card> </Card>
</div> </div>
); );