Skip to content

Commit

Permalink
Account page fixes (#96)
Browse files Browse the repository at this point in the history
* disabled delete own account and more responsive styling

* select all checkbox resets when page changes; fix bug clear ids after each accept/decline

* changed format 2 spaces

* undo works except for mixing individual/multiselect consecutive transactions

* finally done :')

---------

Co-authored-by: Cheryl Chen <[email protected]>
  • Loading branch information
cherhchen and Cheryl Chen authored May 5, 2024
1 parent 2366a1a commit b947e84
Show file tree
Hide file tree
Showing 3 changed files with 574 additions and 406 deletions.
352 changes: 199 additions & 153 deletions src/components/Accounts/ApprovedAccounts.jsx
Original file line number Diff line number Diff line change
@@ -1,177 +1,223 @@
import { NPOBackend } from '../../utils/auth_utils.js';
import { useEffect, useState, useCallback } from 'react';
import { Box, Table, Thead, Tbody, Tr, Th, Td, TableContainer, Button, Checkbox, useDisclosure } from '@chakra-ui/react'
import { CloseIcon } from '@chakra-ui/icons'
import {
Box,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
TableContainer,
Button,
Checkbox,
useDisclosure,
} from '@chakra-ui/react';
import { CloseIcon } from '@chakra-ui/icons';
import DeleteAccountModal from './DeleteAccountModal.jsx';
import PropTypes from 'prop-types';
import PaginationFooter from "../../components/Catalog/PaginationFooter/PaginationFooter";
import PaginationFooter from '../../components/Catalog/PaginationFooter/PaginationFooter';
import { usePagination } from '@ajna/pagination';
import { useAuthContext } from '../../common/AuthContext.jsx';

const ApprovedAccounts = ( {accountType, searchQuery} ) => {
const [approvedAccounts, setApprovedAccounts] = useState([]);
const { isOpen: isDeleteOpen, onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure();
const [deleteItemId, setDeleteItemId] = useState([]);
const [totalRowCount, setTotalRowCount] = useState(0);
const { currentPage, setCurrentPage, pagesCount, offset, pageSize, setPageSize} = usePagination({
initialState: { currentPage: 1, pageSize: 10 },
total: totalRowCount,
});
const [individualChecked, setIndividualChecked] = useState(new Array(approvedAccounts.length).fill(false));
const [checkedAccountIds, setCheckedAccountIds] = useState([]);
const [dataShouldRevalidate, setDataShouldRevalidate] = useState(false);
const ApprovedAccounts = ({ accountType, searchQuery }) => {
const [approvedAccounts, setApprovedAccounts] = useState([]);
const { isOpen: isDeleteOpen, onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure();
const [deleteItemId, setDeleteItemId] = useState([]);
const [totalRowCount, setTotalRowCount] = useState(0);
const { currentPage, setCurrentPage, pagesCount, offset, pageSize, setPageSize } = usePagination({
initialState: { currentPage: 1, pageSize: 10 },
total: totalRowCount,
});
const [individualChecked, setIndividualChecked] = useState(
new Array(approvedAccounts.length).fill(false),
);
const [checkedAccountIds, setCheckedAccountIds] = useState([]);
const [dataShouldRevalidate, setDataShouldRevalidate] = useState(false);
const { currentUser } = useAuthContext();
const [isSelectAll, setIsSelectAll] = useState(false);

const fetchTableData = useCallback(async () => {
try {
const { data } = await NPOBackend.get(`/users/approved-accounts`, {
params: {
keyword: (searchQuery && searchQuery.length) && searchQuery,
page: currentPage,
limit: pageSize,
accountType: accountType}
});
setApprovedAccounts(data.accounts);
setTotalRowCount(Number(data.count[0].count));
} catch (error) {
console.error('Error fetching data:', error);
}
}, [searchQuery, currentPage, pageSize, accountType]);
const fetchTableData = useCallback(async () => {
try {
const { data } = await NPOBackend.get(`/users/approved-accounts`, {
params: {
keyword: searchQuery && searchQuery.length && searchQuery,
page: currentPage,
limit: pageSize,
accountType: accountType,
},
});
setApprovedAccounts(data.accounts);
setTotalRowCount(Number(data.count[0].count));
} catch (error) {
console.error('Error fetching data:', error);
}
}, [searchQuery, currentPage, pageSize, accountType]);

useEffect(() => {
fetchTableData();
}, [fetchTableData]);
useEffect(() => {
fetchTableData();
}, [fetchTableData]);

useEffect(() => {
if (dataShouldRevalidate) {
fetchTableData();
setDataShouldRevalidate(false);
setIndividualChecked(new Array(totalRowCount).fill(false));
setCheckedAccountIds([]);
}
}, [dataShouldRevalidate, fetchTableData, totalRowCount]);
useEffect(() => {
if (dataShouldRevalidate) {
fetchTableData();
setDataShouldRevalidate(false);
setIndividualChecked(new Array(totalRowCount).fill(false));
setCheckedAccountIds([]);
}
}, [dataShouldRevalidate, fetchTableData, totalRowCount]);

useEffect(() => {
setCurrentPage(1);
}, [searchQuery, setCurrentPage, pageSize]);
useEffect(() => {
setCurrentPage(1);
}, [searchQuery, setCurrentPage, pageSize]);

useEffect(() => {
setIndividualChecked(new Array(totalRowCount).fill(false));
setCheckedAccountIds([]);
}, [searchQuery, currentPage, totalRowCount]);
useEffect(() => {
setIndividualChecked(new Array(totalRowCount).fill(false));
setCheckedAccountIds([]);
setIsSelectAll(false);
}, [searchQuery, currentPage, totalRowCount]);

const handleDeleteClick = id => {
setDeleteItemId(id);
onDeleteOpen();
}
const handleDeleteClick = id => {
setDeleteItemId(id);
onDeleteOpen();
};

const updateAllCheckedAccountIds = (e) => {
setIndividualChecked(new Array(approvedAccounts.length).fill(e.target.checked));
if (e.target.checked) {
let allIds = [];
for (let i = 0; i < approvedAccounts.length; i++) {
allIds.push(approvedAccounts[i].id)
}
setCheckedAccountIds(allIds);
const updateAllCheckedAccountIds = e => {
let newIndividualChecked = new Array(approvedAccounts.length).fill(e.target.checked);
if (e.target.checked) {
let allIds = [];
for (let i = 0; i < approvedAccounts.length; i++) {
if (approvedAccounts[i].id != currentUser.id) {
allIds.push(approvedAccounts[i].id);
} else {
setCheckedAccountIds([]);
newIndividualChecked[i] = false;
}
}
setCheckedAccountIds(allIds);
} else {
setCheckedAccountIds([]);
}
setIndividualChecked(newIndividualChecked);
setIsSelectAll(e.target.checked);
};

const updateIndividualCheckedAccountIds = (e, id, index) => {
const newIndividualChecked = [...individualChecked];
newIndividualChecked[index] = e.target.checked;
setIndividualChecked(newIndividualChecked);
let newCheckedAccountIds = [... checkedAccountIds];
if (e.target.checked) {
newCheckedAccountIds.push(id);
setCheckedAccountIds(newCheckedAccountIds);
} else {
let index = newCheckedAccountIds.indexOf(id);
newCheckedAccountIds.splice(index, 1);
setCheckedAccountIds(newCheckedAccountIds);
}
const updateIndividualCheckedAccountIds = (e, id, index) => {
const newIndividualChecked = [...individualChecked];
newIndividualChecked[index] = e.target.checked;
setIndividualChecked(newIndividualChecked);
let newCheckedAccountIds = [...checkedAccountIds];
if (e.target.checked) {
newCheckedAccountIds.push(id);
setCheckedAccountIds(newCheckedAccountIds);
} else {
let index = newCheckedAccountIds.indexOf(id);
newCheckedAccountIds.splice(index, 1);
setCheckedAccountIds(newCheckedAccountIds);
}
};

return (
<Box>
<TableContainer border="1px solid #ededed" borderRadius="10px">
<Table variant='simple'>
<Thead>
<Tr>
<Th w="5%" h="50px"><Checkbox onChange={(e) => { updateAllCheckedAccountIds(e) }}/></Th>
<Th w="30%">Name</Th>
<Th w="30%">Email</Th>
<Th w="0" textAlign="right" >Deactivate</Th>
{checkedAccountIds.length > 0 &&
<Th w="20%" textAlign="right">
<Button isDisabled={checkedAccountIds.length === 0}
onClick={() => { handleDeleteClick(checkedAccountIds) }}
size="xs"
variant="outline"
borderRadius="4px"
borderWidth="1px"
padding="0"
borderColor={checkedAccountIds.length != 0 ? 'red' : 'gray.500'}>
<CloseIcon w="10px" h="10px" color={checkedAccountIds.length != 0 ? 'red' : 'gray'}/>
</Button>
</Th>
}
</Tr>
</Thead>
<Tbody>
{
approvedAccounts.map((account, i) => (
<Tr key={i}>
<Td>
<Checkbox
isChecked={individualChecked[i]}
onChange={(e) => { updateIndividualCheckedAccountIds(e, account.id, i)}}>
</Checkbox>
</Td>
<Td>{account.firstName} {account.lastName}</Td>
<Td>{account.email}</Td>
{checkedAccountIds.length > 0 &&
<Td></Td>
}
<Td textAlign="right">
<Button
onClick={() => { handleDeleteClick([account.id]) }}
size="xs"
variant="outline"
borderColor="gray.500"
borderRadius="4px"
borderWidth="1px"
padding="0"
>
<CloseIcon w="10px" h="10px" color="gray.500"/>
</Button>
</Td>
</Tr>
))
}
</Tbody>
</Table>
<PaginationFooter
pagesCount={pagesCount}
totalRowCount={totalRowCount}
setPageSize={setPageSize}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
rangeString={`${offset + 1} - ${offset + approvedAccounts.length}`}
/>
</TableContainer>
<DeleteAccountModal
isOpen={isDeleteOpen}
onClose={onDeleteClose}
deleteItemId={deleteItemId}
setDataShouldRevalidate={setDataShouldRevalidate}
/>
</Box>
)
}
return (
<Box>
<TableContainer border="1px solid #ededed" borderRadius="10px">
<Table variant="simple">
<Thead>
<Tr>
<Th w="5%" h="50px">
<Checkbox
isChecked={isSelectAll}
onChange={e => {
updateAllCheckedAccountIds(e);
}}
/>
</Th>
<Th w="30%">Name</Th>
<Th w="30%">Email</Th>
<Th w="0" textAlign="right">
Deactivate
</Th>
{checkedAccountIds.length > 0 && (
<Th w="20%" textAlign="right">
<Button
isDisabled={checkedAccountIds.length === 0}
onClick={() => {
handleDeleteClick(checkedAccountIds);
}}
size="xs"
variant="outline"
borderRadius="4px"
borderWidth="1px"
padding="0"
borderColor={checkedAccountIds.length != 0 ? 'red' : 'gray.500'}
>
<CloseIcon
w="10px"
h="10px"
color={checkedAccountIds.length != 0 ? 'red' : 'gray'}
/>
</Button>
</Th>
)}
</Tr>
</Thead>
<Tbody>
{approvedAccounts.map((account, i) => (
<Tr key={i}>
<Td>
<Checkbox
isDisabled={account.id === currentUser.id}
isChecked={individualChecked[i]}
onChange={e => {
updateIndividualCheckedAccountIds(e, account.id, i);
}}
></Checkbox>
</Td>
<Td color={account.id === currentUser.id ? 'gray' : 'black'}>
{account.firstName} {account.lastName}
</Td>
<Td color={account.id === currentUser.id ? 'gray' : 'black'}>{account.email}</Td>
{checkedAccountIds.length > 0 && <Td></Td>}
<Td textAlign="right">
<Button
onClick={() => {
handleDeleteClick([account.id]);
}}
size="xs"
variant="outline"
borderColor="gray.500"
borderRadius="4px"
borderWidth="1px"
padding="0"
isDisabled={account.id === currentUser.id}
>
<CloseIcon w="10px" h="10px" color="gray.500" />
</Button>
</Td>
</Tr>
))}
</Tbody>
</Table>
<PaginationFooter
pagesCount={pagesCount}
totalRowCount={totalRowCount}
setPageSize={setPageSize}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
rangeString={`${offset + 1} - ${offset + approvedAccounts.length}`}
/>
</TableContainer>
<DeleteAccountModal
isOpen={isDeleteOpen}
onClose={onDeleteClose}
deleteItemId={deleteItemId}
setDataShouldRevalidate={setDataShouldRevalidate}
/>
</Box>
);
};

ApprovedAccounts.propTypes = {
accountType: PropTypes.string.isRequired,
searchQuery: PropTypes.string
accountType: PropTypes.string.isRequired,
searchQuery: PropTypes.string,
};

export default ApprovedAccounts;
Loading

0 comments on commit b947e84

Please sign in to comment.