Files
AthenaFE/components/features/logs/LogsTable.tsx
T
2025-11-02 10:08:56 +01:00

135 lines
3.8 KiB
TypeScript

import { useMemo, useState } from "react";
import { View, Text, ScrollView, GestureResponderEvent } from "react-native";
import { LogsTableControls } from "@/components/features/logs/LogsTableControls";
import { TablePagination } from "@/components/shared/TablePagination";
import { UserLoginLog } from "@/store/api/usersApi";
import { useAppSelector } from "@/store/hooks";
import { selectIsMobile } from "@/store/screen/screenSizeSlice";
import { DesktopLogsTable } from "@/components/features/logs/DesktopLogsTable";
import { MobileLogsTable } from "@/components/features/logs/MobileLogsTable";
import { TableSortDirection } from "@/constants/tableSortDirectionEnum";
interface LogsTableProps {
logs: UserLoginLog[];
page: number;
itemsPerPage: number;
totalItems: number;
from: number;
to: number;
searchQuery: string;
onSearch: (q: string) => void;
onItemsPerPageChange: (value: number) => void;
onPageChange: (page: number) => void;
sortColumn: string | null;
sortDirection: TableSortDirection;
onSort: (column: string) => void;
}
export const LogsTable = ({
logs,
page,
itemsPerPage,
totalItems,
from,
to,
searchQuery,
onSearch,
onItemsPerPageChange,
onPageChange,
sortColumn,
sortDirection,
onSort,
}: LogsTableProps) => {
const [menuVisible, setMenuVisible] = useState(false);
const [menuAnchor, setMenuAnchor] = useState<{ x: number; y: number }>({
x: 0,
y: 0,
});
const isMobile = useAppSelector(selectIsMobile);
const handleItemsPerPageButtonPress = (event: GestureResponderEvent) => {
const { pageX, pageY } = event.nativeEvent;
setMenuAnchor({ x: pageX, y: pageY });
setMenuVisible(true);
};
const sortedLogs = useMemo(() => {
if (!sortColumn) return logs;
const dir = sortDirection === TableSortDirection.DESCENDING ? -1 : 1;
const safe = (v?: string) => (v ?? "").toString().toLowerCase();
const out = [...logs];
out.sort((a, b) => {
let comp = 0;
switch (sortColumn) {
case "lastLoginAt": {
const at = new Date(a.lastLoginAt).getTime();
const bt = new Date(b.lastLoginAt).getTime();
comp = at - bt;
break;
}
case "name":
comp = safe(a.name).localeCompare(safe(b.name));
break;
case "email":
comp = safe(a.email).localeCompare(safe(b.email));
break;
case "activity":
comp = safe(a.activity).localeCompare(safe(b.activity));
break;
default:
comp = 0;
}
return comp * dir;
});
return out;
}, [logs, sortColumn, sortDirection]);
return (
<View className="flex-1">
<LogsTableControls
searchQuery={searchQuery}
menuVisible={menuVisible}
menuAnchor={menuAnchor}
onSearch={(q) => onSearch(q)}
onMenuDismiss={() => setMenuVisible(false)}
onItemsPerPageChange={onItemsPerPageChange}
itemsPerPage={itemsPerPage}
/>
{logs.length === 0 ? (
<View
className={`flex-1 items-center justify-center ${
isMobile ? "p-1" : "p-5"
}`}
>
<Text className="text-lg text-gray-500">
No logs match your search{searchQuery && ` for "${searchQuery}"`}
</Text>
</View>
) : isMobile ? (
<MobileLogsTable logs={sortedLogs} />
) : (
<ScrollView className="flex-1">
<DesktopLogsTable
sortColumn={sortColumn}
sortDirection={sortDirection}
onSort={onSort}
logs={sortedLogs}
/>
</ScrollView>
)}
<TablePagination
page={page}
itemsPerPage={itemsPerPage}
totalItems={totalItems}
from={from}
to={to}
onPageChange={onPageChange}
onItemsPerPageButtonPress={handleItemsPerPageButtonPress}
/>
</View>
);
};