project setup

This commit is contained in:
Sone
2025-11-02 10:08:56 +01:00
commit 568838003e
174 changed files with 27100 additions and 0 deletions
@@ -0,0 +1,246 @@
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>
);
};