Skip to content

Commit b236c6e

Browse files
committed
finished everything but account table refresh
1 parent 1ed152d commit b236c6e

File tree

4 files changed

+186
-80
lines changed

4 files changed

+186
-80
lines changed

src/components/Accounts/ApprovedAccounts.jsx

+80-32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NPOBackend } from '../../utils/auth_utils.js';
2-
import { useEffect, useState } from 'react';
3-
import { Box, Table, Thead, Tbody, Tr, Th, Td, TableContainer, Button, Checkbox, useDisclosure, HStack } from '@chakra-ui/react'
2+
import { useEffect, useState, useCallback } from 'react';
3+
import { Box, Table, Thead, Tbody, Tr, Th, Td, TableContainer, Button, Checkbox, useDisclosure } from '@chakra-ui/react'
44
import { CloseIcon } from '@chakra-ui/icons'
55
import DeleteAccountModal from './DeleteAccountModal.jsx';
66
import PropTypes from 'prop-types';
@@ -18,25 +18,58 @@ const ApprovedAccounts = ( {accountType, searchQuery} ) => {
1818
});
1919
const [individualChecked, setIndividualChecked] = useState(new Array(approvedAccounts.length).fill(false));
2020
const [checkedAccountIds, setCheckedAccountIds] = useState([]);
21+
const [dataShouldRevalidate, setDataShouldRevalidate] = useState(false);
22+
23+
// useEffect(() => {
24+
// const renderTable = async () => {
25+
// try {
26+
// const { data } = await NPOBackend.get(`/users/approved-accounts`, {
27+
// params: {
28+
// keyword: (searchQuery && searchQuery.length) && searchQuery,
29+
// page: currentPage,
30+
// limit: pageSize,
31+
// accountType: accountType}
32+
// });
33+
// setApprovedAccounts(data.accounts);
34+
// setTotalRowCount(Number(data.count[0].count));
35+
// } catch (error) {
36+
// console.error('Error fetching data:', error);
37+
// }
38+
// };
39+
// renderTable();
40+
// }, [searchQuery, totalRowCount, currentPage, pageSize, accountType]);
41+
42+
const fetchTableData = useCallback(async () => {
43+
try {
44+
const { data } = await NPOBackend.get(`/users/approved-accounts`, {
45+
params: {
46+
keyword: (searchQuery && searchQuery.length) && searchQuery,
47+
page: currentPage,
48+
limit: pageSize,
49+
accountType: accountType}
50+
});
51+
setApprovedAccounts(data.accounts);
52+
setTotalRowCount(Number(data.count[0].count));
53+
} catch (error) {
54+
console.error('Error fetching data:', error);
55+
}
56+
}, [searchQuery, totalRowCount, currentPage, pageSize, accountType]);
2157

2258
useEffect(() => {
23-
const renderTable = async () => {
24-
try {
25-
const { data } = await NPOBackend.get(`/users/approved-accounts`, {
26-
params: {
27-
keyword: (searchQuery && searchQuery.length) && searchQuery,
28-
page: currentPage,
29-
limit: pageSize,
30-
accountType: accountType}
31-
});
32-
setApprovedAccounts(data.accounts);
33-
setTotalRowCount(Number(data.count[0].count));
34-
} catch (error) {
35-
console.error('Error fetching data:', error);
36-
}
37-
};
38-
renderTable();
39-
}, [searchQuery, totalRowCount, currentPage, pageSize, accountType])
59+
fetchTableData();
60+
}, [fetchTableData]);
61+
62+
useEffect(() => {
63+
if (dataShouldRevalidate) {
64+
console.log(dataShouldRevalidate);
65+
fetchTableData();
66+
setDataShouldRevalidate(false);
67+
}
68+
}, [dataShouldRevalidate, fetchTableData]);
69+
70+
useEffect(() => {
71+
setCurrentPage(1);
72+
}, [searchQuery, setCurrentPage]);
4073

4174
const handleDeleteClick = id => {
4275
setDeleteItemId(id);
@@ -70,33 +103,43 @@ const ApprovedAccounts = ( {accountType, searchQuery} ) => {
70103

71104
return (
72105
<Box>
73-
<TableContainer>
106+
<TableContainer border="1px solid #ededed" borderRadius="10px">
74107
<Table variant='simple'>
75108
<Thead>
76109
<Tr>
77-
<Th width="5%"><Checkbox onChange={(e) => {setIndividualChecked(new Array(approvedAccounts.length).fill(e.target.checked));
110+
<Th w="5%"><Checkbox onChange={(e) => {setIndividualChecked(new Array(approvedAccounts.length).fill(e.target.checked));
78111
updateAllCheckedAccountIds(e)}}/>
79112
</Th>
80113
<Th>Name</Th>
81114
<Th>Email</Th>
82-
<HStack>
83-
<Th>Deactivate</Th>
84-
<Button onClick={() => { handleDeleteClick(checkedAccountIds) }} size='sm' variant='outline'><CloseIcon w={3} h={3} color='gray'/></Button>
85-
</HStack>
115+
<Th w="0">Deactivate</Th>
116+
<Th>
117+
<Button isDisabled={checkedAccountIds.length === 0}
118+
onClick={() => { handleDeleteClick(checkedAccountIds) }}
119+
size='sm'
120+
variant='outline'
121+
borderColor={checkedAccountIds.length != 0 ? 'red' : 'gray'}>
122+
<CloseIcon w={3} h={3} color={checkedAccountIds.length != 0 ? 'red' : 'gray'}/>
123+
</Button>
124+
</Th>
86125
</Tr>
87126
</Thead>
88127
<Tbody>
89128
{
90129
approvedAccounts.map((account, i) => (
91130
<Tr key={i}>
92-
<Td><Checkbox isChecked={individualChecked[i]} onChange={(e) => {const newIndividualChecked = [...individualChecked];
93-
newIndividualChecked[i] = e.target.checked;
94-
setIndividualChecked(newIndividualChecked);
95-
updateIndividualCheckedAccountIds(e, account.id)}}>
131+
<Td>
132+
<Checkbox
133+
isChecked={individualChecked[i]}
134+
onChange={(e) => {const newIndividualChecked = [...individualChecked];
135+
newIndividualChecked[i] = e.target.checked;
136+
setIndividualChecked(newIndividualChecked);
137+
updateIndividualCheckedAccountIds(e, account.id)}}>
96138
</Checkbox>
97139
</Td>
98140
<Td>{account.firstName} {account.lastName}</Td>
99141
<Td>{account.email}</Td>
142+
<Td></Td>
100143
<Td>
101144
<Button onClick={() => { handleDeleteClick([account.id]) }} size='sm' variant='outline'><CloseIcon w={3} h={3} color='gray'/></Button>
102145
</Td>
@@ -105,15 +148,20 @@ const ApprovedAccounts = ( {accountType, searchQuery} ) => {
105148
}
106149
</Tbody>
107150
</Table>
108-
</TableContainer>
109-
<DeleteAccountModal isOpen={isDeleteOpen} onClose={onDeleteClose} deleteItemId={deleteItemId} />
110-
<PaginationFooter
151+
<PaginationFooter
111152
pagesCount={pagesCount}
112153
totalRowCount={totalRowCount}
113154
setPageSize={setPageSize}
114155
currentPage={currentPage}
115156
setCurrentPage={setCurrentPage}
116157
rangeString={`${offset + 1} - ${offset + Number(pageSize)}`}
158+
/>
159+
</TableContainer>
160+
<DeleteAccountModal
161+
isOpen={isDeleteOpen}
162+
onClose={onDeleteClose}
163+
deleteItemId={deleteItemId}
164+
setDataShouldRevalidate={setDataShouldRevalidate}
117165
/>
118166
</Box>
119167
)

src/components/Accounts/DeleteAccountModal.jsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '@chakra-ui/react';
1212
import { NPOBackend } from '../../utils/auth_utils.js';
1313

14-
const DeleteAccountModal = ({ isOpen, onClose, deleteItemId}) => {
14+
const DeleteAccountModal = ({ isOpen, onClose, deleteItemId, setDataShouldRevalidate}) => {
1515
const handleConfirmDelete = async idToDelete => {
1616
try {
1717
for (let i = 0; i < idToDelete.length; i++) {
@@ -32,7 +32,7 @@ const DeleteAccountModal = ({ isOpen, onClose, deleteItemId}) => {
3232
<ModalBody>Are you sure? You cannot undo this action afterwards.</ModalBody>
3333
<ModalFooter gap='3'>
3434
<Button onClick={onClose}>Cancel</Button>
35-
<Button onClick={() => handleConfirmDelete(deleteItemId)} colorScheme='red'>Delete</Button>
35+
<Button onClick={() => {handleConfirmDelete(deleteItemId); setDataShouldRevalidate(true);}} colorScheme='red'>Delete</Button>
3636
</ModalFooter>
3737
</ModalContent>
3838
</Modal>
@@ -43,6 +43,7 @@ DeleteAccountModal.propTypes = {
4343
isOpen: PropTypes.bool.isRequired,
4444
onClose: PropTypes.func.isRequired,
4545
deleteItemId: PropTypes.string.isRequired,
46+
setDataShouldRevalidate: PropTypes.func.isRequired
4647
};
4748

4849
export default DeleteAccountModal;
+73-30
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,41 @@
11
import { NPOBackend } from '../../utils/auth_utils.js';
22
import { useEffect, useState } from 'react';
3-
import { Table, Thead, Tbody, Tr, Th, Td, TableContainer, Button, HStack } from '@chakra-ui/react'
3+
import { Table, Thead, Tbody, Tr, Th, Td, TableContainer, Button } from '@chakra-ui/react'
44
import { Checkbox } from '@chakra-ui/react'
55
import PropTypes from 'prop-types';
66

7-
const PendingAccounts = ( {accountType, searchQuery} ) => {
7+
const PendingAccounts = ( {accountType, setHasPendingAccounts} ) => {
88
const [pendingAccounts, setPendingAccounts] = useState([]);
99
const [individualChecked, setIndividualChecked] = useState(new Array(pendingAccounts.length).fill(false));
1010
const [checkedAccountIds, setCheckedAccountIds] = useState([]);
11+
const [accountStatus, setAccountStatus] = useState({});
12+
1113

1214
useEffect(() => {
1315
const renderTable = async () => {
14-
const { data } = await NPOBackend.get('/users/pending-accounts', {
15-
params : {
16-
keyword: searchQuery
17-
}
18-
});
16+
const { data } = await NPOBackend.get('/users/pending-accounts', {params: {accountType: accountType}});
1917
setPendingAccounts(data);
18+
console.log("ELNGLKNKJ: " + data);
19+
setHasPendingAccounts(data.length !== 0);
2020
};
2121
renderTable();
22+
}, [])
23+
24+
useEffect(() => {
25+
const newAccountStatus = {}
26+
for (let i = 0; i < pendingAccounts.length; i++) {
27+
newAccountStatus[pendingAccounts[i]["id"]] = "pending";
28+
}
29+
setAccountStatus(newAccountStatus);
2230
}, [pendingAccounts])
2331

2432
const handleApproveUser = async (ids) => {
2533
try {
2634
for (let i = 0; i < ids.length; i++) {
35+
console.log("approved: " + ids[i]);
2736
await NPOBackend.put(`/users/approve/${ids[i]}`);
2837
}
38+
setIndividualChecked(new Array(pendingAccounts.length).fill(false));
2939
} catch (error) {
3040
console.log(error);
3141
}
@@ -34,8 +44,10 @@ const PendingAccounts = ( {accountType, searchQuery} ) => {
3444
const handleDeleteUser = async (ids) => {
3545
try {
3646
for (let i = 0; i < ids.length; i++) {
47+
console.log("deleted: " + ids[i]);
3748
await NPOBackend.delete(`/users/${ids[i]}`);
3849
}
50+
setIndividualChecked(new Array(pendingAccounts.length).fill(false));
3951
} catch (error) {
4052
console.log(error);
4153
}
@@ -66,8 +78,28 @@ const PendingAccounts = ( {accountType, searchQuery} ) => {
6678
console.log(newCheckedAccountIds);
6779
}
6880

81+
useEffect(() => console.log("accountStatus: " + JSON.stringify(accountStatus)), [accountStatus]);
82+
83+
const acceptAllClick = () => {
84+
handleApproveUser(checkedAccountIds);
85+
const newAccountStatus = {... accountStatus};
86+
for (let i = 0; i < checkedAccountIds.length; i++) {
87+
newAccountStatus[checkedAccountIds[i]] = "approved";
88+
}
89+
setAccountStatus(newAccountStatus);
90+
}
91+
92+
const deleteAllClick = () => {
93+
handleDeleteUser(checkedAccountIds);
94+
const newAccountStatus = {... accountStatus};
95+
for (let i = 0; i < checkedAccountIds.length; i++) {
96+
newAccountStatus[checkedAccountIds[i]] = "declined";
97+
}
98+
setAccountStatus(newAccountStatus);
99+
}
100+
69101
return (
70-
<TableContainer>
102+
<TableContainer border="1px solid #ededed" borderRadius="10px">
71103
<Table variant='simple'>
72104
<Thead>
73105
<Tr>
@@ -76,34 +108,45 @@ const PendingAccounts = ( {accountType, searchQuery} ) => {
76108
</Th>
77109
<Th>Name</Th>
78110
<Th>Email</Th>
79-
<HStack>
80-
<Th>Action</Th>
81-
<Button onClick={() => { handleApproveUser(checkedAccountIds) }} mr={3} colorScheme='blue'>Accept</Button>
82-
<Button onClick={() => { handleDeleteUser(checkedAccountIds) }}>Decline</Button>
83-
</HStack>
111+
<Th width="0">Action</Th>
112+
<Th>
113+
<Button isDisabled={checkedAccountIds.length === 0} onClick={ acceptAllClick } mr={3} colorScheme='blue'>Accept</Button>
114+
<Button isDisabled={checkedAccountIds.length === 0} onClick={ deleteAllClick }>Decline</Button>
115+
</Th>
84116
</Tr>
85117
</Thead>
86118
<Tbody>
87119
{
88120
pendingAccounts.map((account, i) => (
89-
accountType === account.type ? (
90-
<Tr key={i}>
91-
<Td><Checkbox isChecked={individualChecked[i]} onChange={(e) => {const newIndividualChecked = [...individualChecked];
92-
newIndividualChecked[i] = e.target.checked;
93-
setIndividualChecked(newIndividualChecked);
94-
updateIndividualCheckedAccountIds(e, account.id)}}>
95-
</Checkbox>
96-
</Td>
97-
<Td>{account.firstName} {account.lastName}</Td>
98-
<Td>{account.email}</Td>
121+
<Tr key={i}>
122+
<Td><Checkbox isDisabled={accountStatus[account.id] != "pending"} isChecked={individualChecked[i]} onChange={(e) => {const newIndividualChecked = [...individualChecked];
123+
newIndividualChecked[i] = e.target.checked;
124+
setIndividualChecked(newIndividualChecked);
125+
updateIndividualCheckedAccountIds(e, account.id);}}>
126+
</Checkbox>
127+
</Td>
128+
<Td color={accountStatus[account.id] === "pending" ? "black" : "gray"}>{account.firstName} {account.lastName}</Td>
129+
<Td color={accountStatus[account.id] === "pending" ? "black" : "gray"}>{account.email}</Td>
130+
<Td></Td>
131+
{
132+
accountStatus[account.id] === "pending" ? (
99133
<Td>
100-
<Button onClick={() => { handleApproveUser([account.id]) }} mr={3} colorScheme='blue'>Accept</Button>
101-
<Button onClick={() => { handleDeleteUser([account.id]) }}>Decline</Button>
134+
<Button onClick={() => { handleApproveUser([account.id]);
135+
const newAccountStatus = {... accountStatus};
136+
newAccountStatus[account.id] = "approved";
137+
setAccountStatus(newAccountStatus); }} mr={3} colorScheme='blue'>Accept</Button>
138+
<Button onClick={() => { handleDeleteUser([account.id]);
139+
const newAccountStatus = {... accountStatus};
140+
newAccountStatus[account.id] = "declined";
141+
setAccountStatus(newAccountStatus); }}>Decline</Button>
102142
</Td>
103-
</Tr>
104-
) : (
105-
<></>
106-
)
143+
) : accountStatus[account.id] === "approved" ? (
144+
<Td color="green">Approved</Td>
145+
) : (
146+
<Td color="red">Declined</Td>
147+
)
148+
}
149+
</Tr>
107150
)
108151
)
109152
}
@@ -115,7 +158,7 @@ const PendingAccounts = ( {accountType, searchQuery} ) => {
115158

116159
PendingAccounts.propTypes = {
117160
accountType: PropTypes.string.isRequired,
118-
searchQuery: PropTypes.string
161+
setHasPendingAccounts: PropTypes.func.isRequired
119162
};
120163

121164
export default PendingAccounts;

0 commit comments

Comments
 (0)