247 lines
6.8 KiB
TypeScript
247 lines
6.8 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { View, GestureResponderEvent, ScrollView, Text } from "react-native";
|
|
|
|
import { User } from "@/store/models/User.model";
|
|
import { useAppSelector } from "@/store/hooks";
|
|
import { selectIsMobile } from "@/store/screen/screenSizeSlice";
|
|
import { UserTableControls } from "@/components/features/users/UserTableControls";
|
|
import { DesktopUserAccountsTable } from "@/components/features/users/DesktopUserAccountsTable";
|
|
import { MobileUserAccountsTable } from "@/components/features/users/MobileUserAccountsTable";
|
|
import { TablePagination } from "@/components/shared/TablePagination";
|
|
import { TableSortDirection } from "@/constants/tableSortDirectionEnum";
|
|
import { RiskEnum } from "@/constants/riskEnum";
|
|
|
|
interface UserAccountsTableProps {
|
|
users: User[];
|
|
onEdit: (user: User) => void;
|
|
onAddUser: () => void;
|
|
onDelete: (user: User) => void;
|
|
onLock: (user: User) => void;
|
|
onSelect: (userIds: string[]) => void;
|
|
onBulkDelete: (users: User[]) => void;
|
|
selectedUserIds?: string[];
|
|
page: number;
|
|
itemsPerPage: number;
|
|
totalItems: number;
|
|
from: number;
|
|
to: number;
|
|
searchQuery: string;
|
|
selectedRisks: RiskEnum[];
|
|
sortColumn: string | null;
|
|
sortDirection: TableSortDirection;
|
|
onSearch: (q: string) => void;
|
|
onSelectRisks: (risks: RiskEnum[]) => void;
|
|
onSort: (column: string) => void;
|
|
onItemsPerPageChange: (value: number) => void;
|
|
onPageChange: (page: number) => void;
|
|
onAddingUser: boolean;
|
|
}
|
|
|
|
export const UserAccountsTable = ({
|
|
users,
|
|
onEdit,
|
|
onAddUser,
|
|
onDelete,
|
|
onLock,
|
|
onSelect,
|
|
onBulkDelete,
|
|
selectedUserIds,
|
|
page,
|
|
itemsPerPage,
|
|
totalItems,
|
|
from,
|
|
to,
|
|
searchQuery,
|
|
selectedRisks,
|
|
sortColumn,
|
|
sortDirection,
|
|
onSearch,
|
|
onSelectRisks,
|
|
onSort,
|
|
onItemsPerPageChange,
|
|
onPageChange,
|
|
onAddingUser,
|
|
}: UserAccountsTableProps) => {
|
|
const [selectedUsers, setSelectedUsers] = useState<string[]>([]);
|
|
const [selectAll, setSelectAll] = useState(false);
|
|
const [menuVisible, setMenuVisible] = useState(false);
|
|
const [menuAnchor, setMenuAnchor] = useState<{ x: number; y: number }>({
|
|
x: 0,
|
|
y: 0,
|
|
});
|
|
const [prevSelectedUserIds, setPrevSelectedUserIds] = useState<
|
|
string[] | undefined
|
|
>(selectedUserIds);
|
|
const isMobile = useAppSelector(selectIsMobile);
|
|
|
|
const handleSort = (column: string) => onSort(column);
|
|
const handleSearch = (query: string) => onSearch(query);
|
|
const handleSelectRisks = (risks: RiskEnum[]) => onSelectRisks(risks);
|
|
const handleItemsPerPageChange = (value: number) =>
|
|
onItemsPerPageChange(value);
|
|
|
|
const handleSelectAll = () => {
|
|
if (selectAll) {
|
|
setSelectedUsers([]);
|
|
} else {
|
|
setSelectedUsers(users.map((user) => user.id) || []);
|
|
}
|
|
setSelectAll(!selectAll);
|
|
};
|
|
|
|
const handleSelectUser = (userId: string) => {
|
|
if (selectedUsers.includes(userId)) {
|
|
setSelectedUsers(selectedUsers.filter((id) => id !== userId));
|
|
} else {
|
|
setSelectedUsers([...selectedUsers, userId]);
|
|
}
|
|
};
|
|
|
|
const handleBulkDelete = () => {
|
|
if (selectedUsers.length === 0) return;
|
|
|
|
const selectedUserObjects = users.filter((user) =>
|
|
selectedUsers.includes(user.id)
|
|
);
|
|
|
|
if (onBulkDelete) {
|
|
onBulkDelete(selectedUserObjects || []);
|
|
} else {
|
|
alert(`Would delete ${selectedUsers.length} users`);
|
|
}
|
|
|
|
if (onSelect) {
|
|
onSelect(selectedUsers);
|
|
}
|
|
};
|
|
|
|
const handleEdit = (user: User) => {
|
|
if (onEdit) {
|
|
onEdit(user);
|
|
} else {
|
|
alert(`Edit user: ${user.firstName} ${user.lastName}`);
|
|
}
|
|
};
|
|
|
|
const handleDelete = (user: User) => {
|
|
if (onDelete) {
|
|
onDelete(user);
|
|
} else {
|
|
alert(`Delete user: ${user.firstName} ${user.lastName}`);
|
|
}
|
|
};
|
|
|
|
const handleLock = (user: User) => {
|
|
if (onLock) {
|
|
onLock(user);
|
|
} else {
|
|
alert(`Lock user: ${user.firstName} ${user.lastName}`);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (onSelect) {
|
|
onSelect(selectedUsers);
|
|
}
|
|
}, [selectedUsers, onSelect]);
|
|
|
|
useEffect(() => {
|
|
if (
|
|
prevSelectedUserIds &&
|
|
prevSelectedUserIds.length > 0 &&
|
|
selectedUserIds &&
|
|
selectedUserIds.length === 0
|
|
) {
|
|
setSelectedUsers([]);
|
|
setSelectAll(false);
|
|
}
|
|
|
|
setPrevSelectedUserIds(selectedUserIds);
|
|
}, [selectedUserIds, prevSelectedUserIds]);
|
|
|
|
useEffect(() => {
|
|
const validSelectedUsers = selectedUsers.filter((userId) =>
|
|
users.some((user) => user.id === userId)
|
|
);
|
|
|
|
if (validSelectedUsers.length !== selectedUsers.length) {
|
|
setSelectedUsers(validSelectedUsers);
|
|
}
|
|
|
|
const allDisplayedSelected =
|
|
users.every((user) => validSelectedUsers.includes(user.id)) ?? false;
|
|
setSelectAll(allDisplayedSelected && users.length > 0);
|
|
}, [users, selectedUsers]);
|
|
|
|
return (
|
|
<View className="flex-1">
|
|
<UserTableControls
|
|
searchQuery={searchQuery}
|
|
selectAll={selectAll}
|
|
selectedItems={selectedUsers}
|
|
menuVisible={menuVisible}
|
|
menuAnchor={menuAnchor}
|
|
selectedRisks={selectedRisks}
|
|
onSearch={handleSearch}
|
|
onSelectAll={handleSelectAll}
|
|
onBulkDelete={handleBulkDelete}
|
|
onMenuDismiss={() => setMenuVisible(false)}
|
|
onItemsPerPageChange={handleItemsPerPageChange}
|
|
onSelectRisks={handleSelectRisks}
|
|
onAddUser={onAddUser}
|
|
onAddingUser={onAddingUser}
|
|
itemsPerPage={itemsPerPage}
|
|
/>
|
|
|
|
{users.length === 0 ? (
|
|
<View
|
|
className={`flex-1 items-center justify-center ${
|
|
isMobile ? "p-1" : "p-5"
|
|
}`}
|
|
>
|
|
<Text className="text-lg text-gray-500">
|
|
No users match your search{searchQuery && ` for "${searchQuery}"`}
|
|
</Text>
|
|
</View>
|
|
) : isMobile ? (
|
|
<MobileUserAccountsTable
|
|
users={users}
|
|
selectedUsers={selectedUsers}
|
|
onSelectUser={handleSelectUser}
|
|
onEdit={handleEdit}
|
|
onLock={handleLock}
|
|
onDelete={handleDelete}
|
|
/>
|
|
) : (
|
|
<ScrollView className="flex-1">
|
|
<DesktopUserAccountsTable
|
|
users={users}
|
|
selectedUsers={selectedUsers}
|
|
sortColumn={sortColumn}
|
|
sortDirection={sortDirection}
|
|
onSort={handleSort}
|
|
onSelectUser={handleSelectUser}
|
|
onEdit={handleEdit}
|
|
onLock={handleLock}
|
|
onDelete={handleDelete}
|
|
/>
|
|
</ScrollView>
|
|
)}
|
|
|
|
<TablePagination
|
|
page={page}
|
|
itemsPerPage={itemsPerPage}
|
|
totalItems={totalItems}
|
|
from={from}
|
|
to={to}
|
|
onPageChange={onPageChange}
|
|
onItemsPerPageButtonPress={(event: GestureResponderEvent) => {
|
|
const { pageX, pageY } = event.nativeEvent;
|
|
setMenuAnchor({ x: pageX, y: pageY });
|
|
setMenuVisible(true);
|
|
}}
|
|
/>
|
|
</View>
|
|
);
|
|
};
|