Skip to content

Commit 0f6f3bb

Browse files
committed
Convert security admin dashboard to typescript
1 parent ff38a1a commit 0f6f3bb

2 files changed

Lines changed: 62 additions & 47 deletions

File tree

client/src/components/Account/SecurityAdminDashboard/SecurityAdminDashboard.jsx renamed to client/src/components/Account/SecurityAdminDashboard/SecurityAdminDashboard.tsx

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { Container, TextField, Typography } from "@mui/material";
22
import debounce from "lodash.debounce";
3-
import { useEffect, useMemo, useState } from "react";
3+
import { useEffect, useMemo, useState, ChangeEvent } from "react";
44
import * as accountService from "../../../services/account-service";
5-
import SecurityTable from "./SecurityTable";
5+
import SecurityTable, { Account } from "./SecurityTable";
66

77
const SecurityAdminDashboard = () => {
8-
const [accounts, setAccounts] = useState([]);
9-
const [filteredAccounts, setFilteredAccounts] = useState([]);
10-
const [search, setSearch] = useState("");
11-
const [error, setError] = useState("");
8+
const [accounts, setAccounts] = useState<Account[]>([]);
9+
const [filteredAccounts, setFilteredAccounts] = useState<Account[]>([]);
10+
const [search, setSearch] = useState<string>("");
11+
const [error, setError] = useState<string>("");
1212

1313
useEffect(() => {
1414
const fetchData = async () => {
@@ -23,7 +23,7 @@ const SecurityAdminDashboard = () => {
2323
}, []);
2424

2525
useEffect(() => {
26-
if (accounts.length === 0) return undefined;
26+
if (accounts.length === 0) return;
2727
if (search.length === 0) {
2828
setError("");
2929
setFilteredAccounts(accounts);
@@ -42,35 +42,37 @@ const SecurityAdminDashboard = () => {
4242
}, [search, accounts]);
4343

4444
const debouncedChangeHandler = useMemo(() => {
45-
const changeHandler = (event) => {
45+
const changeHandler = (event: ChangeEvent<HTMLInputElement>) => {
4646
setSearch(event.target.value.toLowerCase());
4747
};
4848
return debounce(changeHandler, 300);
49-
}, [setSearch]);
49+
}, []);
5050

51-
const handlePermissionChange = (userId, permission, value) => {
52-
const account = filteredAccounts.find((row) => {
53-
return row.id === userId;
54-
});
51+
const handlePermissionChange = (
52+
userId: number,
53+
permission: string,
54+
value: boolean
55+
) => {
56+
const account = filteredAccounts.find((row) => row.id === userId);
5557
if (account) {
5658
if (permission === "is_admin") {
57-
account["isAdmin"] = value;
59+
account.isAdmin = value;
5860
} else if (permission === "is_coordinator") {
59-
account["isCoordinator"] = value;
61+
account.isCoordinator = value;
6062
} else if (permission === "is_security_admin") {
61-
account["isSecurityAdmin"] = value;
63+
account.isSecurityAdmin = value;
6264
} else if (permission === "is_data_entry") {
63-
account["isDataEntry"] = value;
65+
account.isDataEntry = value;
6466
} else if (permission === "is_global_admin") {
65-
account["isGlobalAdmin"] = value;
67+
account.isGlobalAdmin = value;
6668
} else if (permission === "is_global_reporting") {
67-
account["isGlobalReporting"] = value;
69+
account.isGlobalReporting = value;
6870
}
6971
}
7072
let filtered = [...filteredAccounts, { ...account }];
7173
const unique = [
72-
...new Map(filtered.map((item) => [item.id, item])).values(),
73-
];
74+
...new Map(filtered.map((item) => [item?.id, item])).values(),
75+
] as Account[];
7476
setFilteredAccounts(unique);
7577
};
7678

client/src/components/Account/SecurityAdminDashboard/SecurityTable.jsx renamed to client/src/components/Account/SecurityAdminDashboard/SecurityTable.tsx

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,41 @@ import {
88
TableHead,
99
TableRow,
1010
} from "@mui/material";
11-
import PropTypes from "prop-types";
1211
import { useUserContext } from "../../../contexts/userContext";
1312
import * as accountService from "../../../services/account-service";
1413

15-
export default function SecurityTable(props) {
14+
export interface Account {
15+
id: number;
16+
email: string;
17+
firstName: string;
18+
lastName: string;
19+
isAdmin?: boolean;
20+
isCoordinator?: boolean;
21+
isSecurityAdmin?: boolean;
22+
isDataEntry?: boolean;
23+
isGlobalAdmin?: boolean;
24+
isGlobalReporting?: boolean;
25+
}
26+
27+
export interface SecurityTableProps {
28+
accounts: Account[];
29+
handlePermissionChange: (
30+
userId: number,
31+
permission: string,
32+
value: boolean
33+
) => Promise<void> | void;
34+
}
35+
36+
export default function SecurityTable(props: SecurityTableProps) {
1637
const { user } = useUserContext();
1738

1839
// arg `roleType` is expected to be one of:
1940
// 'security', 'admin, 'dataEntry', or 'coordinator'
20-
const handleToggle = (userId, e, roleType) => {
41+
const handleToggle = (
42+
userId: number,
43+
e: React.ChangeEvent<HTMLInputElement>,
44+
roleType: "security" | "admin" | "dataEntry" | "coordinator"
45+
) => {
2146
if (roleType === "security") {
2247
props.accounts.map(async (each) => {
2348
if (userId === each.id) {
@@ -63,7 +88,11 @@ export default function SecurityTable(props) {
6388

6489
// arg `roleType` is expected to be one of:
6590
// 'globalAdmin' or 'globalReporting'
66-
const handleGlobalToggle = (userId, e, roleType) => {
91+
const handleGlobalToggle = (
92+
userId: number,
93+
e: React.ChangeEvent<HTMLInputElement>,
94+
roleType: "globalAdmin" | "globalReporting"
95+
) => {
6796
if (roleType === "globalAdmin") {
6897
props.accounts.map(async (each) => {
6998
if (userId === each.id) {
@@ -165,15 +194,15 @@ export default function SecurityTable(props) {
165194
<>
166195
<TableCell align="right">
167196
<Checkbox
168-
checked={row.isGlobalAdmin}
197+
checked={Boolean(row.isGlobalAdmin)}
169198
onChange={(e) =>
170199
handleGlobalToggle(row.id, e, "globalAdmin")
171200
}
172201
/>
173202
</TableCell>
174203
<TableCell align="right">
175204
<Checkbox
176-
checked={row.isGlobalReporting}
205+
checked={Boolean(row.isGlobalReporting)}
177206
onChange={(e) =>
178207
handleGlobalToggle(row.id, e, "globalReporting")
179208
}
@@ -183,25 +212,25 @@ export default function SecurityTable(props) {
183212
) : null}
184213
<TableCell align="right">
185214
<Checkbox
186-
checked={row.isAdmin}
215+
checked={Boolean(row.isAdmin)}
187216
onChange={(e) => handleToggle(row.id, e, "admin")}
188217
/>
189218
</TableCell>
190219
<TableCell align="right">
191220
<Checkbox
192-
checked={row.isCoordinator}
221+
checked={Boolean(row.isCoordinator)}
193222
onChange={(e) => handleToggle(row.id, e, "coordinator")}
194223
/>
195224
</TableCell>
196225
<TableCell align="right">
197226
<Checkbox
198-
checked={row.isSecurityAdmin}
227+
checked={Boolean(row.isSecurityAdmin)}
199228
onChange={(e) => handleToggle(row.id, e, "security")}
200229
/>
201230
</TableCell>
202231
<TableCell align="right">
203232
<Checkbox
204-
checked={row.isDataEntry}
233+
checked={Boolean(row.isDataEntry)}
205234
onChange={(e) => handleToggle(row.id, e, "dataEntry")}
206235
/>
207236
</TableCell>
@@ -212,19 +241,3 @@ export default function SecurityTable(props) {
212241
</TableContainer>
213242
);
214243
}
215-
216-
SecurityTable.propTypes = {
217-
accounts: PropTypes.arrayOf(
218-
PropTypes.shape({
219-
id: PropTypes.number.isRequired,
220-
email: PropTypes.string.isRequired,
221-
firstName: PropTypes.string.isRequired,
222-
lastName: PropTypes.string.isRequired,
223-
isAdmin: PropTypes.bool,
224-
isCoordinator: PropTypes.bool,
225-
isSecurityAdmin: PropTypes.bool,
226-
isDataEntry: PropTypes.bool,
227-
}).isRequired
228-
),
229-
handlePermissionChange: PropTypes.func.isRequired,
230-
};

0 commit comments

Comments
 (0)