import { useState, useMemo, memo } from "react"; import { Text, TextInput, Stack, Group, Box, Container, Divider, UnstyledButton, Select, Pagination, Code, Alert, } from "@mantine/core"; import { MagnifyingGlassIcon, CaretUpIcon, CaretDownIcon, CheckIcon, XIcon, ChecksIcon, } from "@phosphor-icons/react"; import { Activity, ActivitySearchParams } from "../types"; import { useActivities } from "../queries"; import Sheet from "@/components/sheet/sheet"; import { useSheet } from "@/hooks/use-sheet"; interface ActivityListItemProps { activity: Activity; onClick: () => void; } const ActivityListItem = memo(({ activity, onClick }: ActivityListItemProps) => { const playerName = typeof activity.player === "object" && activity.player ? `${activity.player.first_name} ${activity.player.last_name}` : "System"; const formatDate = (dateStr: string) => { const date = new Date(dateStr); return date.toLocaleString(); }; return ( {activity.name} {activity.success ? ( ) : ( )} {playerName} {activity.duration}ms {formatDate(activity.created)} {activity.error && ( {activity.error} )} ); }); interface ActivityDetailsSheetProps { activity: Activity | null; isOpen: boolean; onClose: () => void; } const ActivityDetailsSheet = memo(({ activity, isOpen, onClose }: ActivityDetailsSheetProps) => { if (!activity) return null; const playerName = typeof activity.player === "object" && activity.player ? `${activity.player.first_name} ${activity.player.last_name}` : "System"; const formatDate = (dateStr: string) => { const date = new Date(dateStr); return date.toLocaleString(); }; return ( Function Name {activity.name} Status {activity.success ? ( <> Success ) : ( <> Failed )} Player {playerName} Duration {activity.duration}ms Created {formatDate(activity.created)} {activity.user_agent && ( User Agent {activity.user_agent} )} {activity.error && ( Error Message {activity.error} )} {activity.arguments && ( Arguments {JSON.stringify(activity.arguments, null, 2)} )} ); }); const ActivitiesResults = ({ searchParams, page, setPage, onActivityClick }: any) => { const { data: result } = useActivities(searchParams); return ( <> {result.items.map((activity: Activity, index: number) => ( onActivityClick(activity)} /> {index < result.items.length - 1 && } ))} {result.items.length === 0 && ( No activities found )} {result.totalPages > 1 && ( )} ); }; export const ActivitiesTable = () => { const [page, setPage] = useState(1); const [search, setSearch] = useState(""); const [successFilter, setSuccessFilter] = useState(null); const [sortBy, setSortBy] = useState("-created"); const [selectedActivity, setSelectedActivity] = useState(null); const { isOpen: detailsOpened, open: openDetails, close: closeDetails, } = useSheet(); const searchParams: ActivitySearchParams = useMemo( () => ({ page, perPage: 100, name: search || undefined, success: successFilter === "success" ? true : successFilter === "failure" ? false : undefined, sortBy, }), [page, search, successFilter, sortBy] ); const { data: result } = useActivities(searchParams); const handleSort = (field: string) => { setSortBy((prev) => { if (prev === field) return `-${field}`; if (prev === `-${field}`) return field; return `-${field}`; }); }; const getSortIcon = (field: string) => { if (sortBy === field) return ; if (sortBy === `-${field}`) return ; return null; }; const handleActivityClick = (activity: Activity) => { setSelectedActivity(activity); openDetails(); }; const handleCloseDetails = () => { setSelectedActivity(null); closeDetails(); }; return ( { setSearch(e.currentTarget.value); setPage(1); }} leftSection={} size="md" />