Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | 'use client'; import React, { useCallback, useContext, useEffect, useState } from 'react'; import Button from 'react-bootstrap/Button'; import Table from 'react-bootstrap/Table'; import DepartmentSettingsModal from '@/components/departmentSettings/DepartmentSettingsModal'; import LoadingSpinner from '@/components/loadingSpinner/loadingSpinner'; import { Department, ListDepartmentApi } from '@/types/api/departments'; import { FrontendUserObject, UserDepartment } from '@/types/api/users'; import { getLogger } from '@/utils/common/logger'; import { getUserPermissions } from '@/utils/common/user'; import { AddAlertContext, LoggedInUserContext } from '@/utils/frontend/clientContexts'; import { typeFetch } from '@/utils/frontend/typeFetch'; const logger = getLogger('departmentsPage'); export default function DepartmentsPage() { const [ isLoading, setIsLoading, ] = useState(false); const [ departments, setDepartments, ] = useState<Department[] | null>(null); const [ selectedDepartment, setSelectedDepartment, ] = useState<Department | null>(null); const loggedInUser = useContext(LoggedInUserContext); const addAlert = useContext(AddAlertContext); useEffect(() => { (async () => { setIsLoading(true); const [ code, apiResult, ] = await typeFetch<ListDepartmentApi>({ path: '/api/v2/departments/', method: 'GET', }); if ( code !== 200 || apiResult === null || !Array.isArray(apiResult) ) { logger.error('Failed to get departments', code, apiResult); addAlert('danger', 'Failed to load departments'); setIsLoading(false); return; } setDepartments(apiResult); setIsLoading(false); })(); }, [ addAlert, ]); // Filter departments based on user permissions const userPerms = getUserPermissions(loggedInUser as FrontendUserObject); const filteredDepartments = departments?.filter(dept => { if (userPerms.isDistrictAdmin) { return true; // District admins see all } // Department admins see only their departments return userPerms.adminDepartments.includes(dept.id as UserDepartment); }) ?? []; const handleEditClick = useCallback((dept: Department) => { setSelectedDepartment(dept); }, []); const handleModalClose = useCallback(() => { setSelectedDepartment(null); }, []); const handleUpdate = useCallback(() => { // Refetch departments after update (async () => { const [ code, apiResult, ] = await typeFetch<ListDepartmentApi>({ path: '/api/v2/departments/', method: 'GET', }); if ( code !== 200 || apiResult === null || !Array.isArray(apiResult) ) { logger.error('Failed to refresh departments', code, apiResult); return; } setDepartments(apiResult); setSelectedDepartment(null); addAlert('success', 'Department updated successfully'); })(); }, [ addAlert, ]); if (isLoading) { return <LoadingSpinner />; } if (!departments || filteredDepartments.length === 0) { return <h1 className='text-center'>No departments found</h1>; } return <> <Table responsive={true} striped bordered> <thead> <tr> <th>Department Name</th> <th>Action</th> </tr> </thead> <tbody> {filteredDepartments.map(dept => { return <tr key={dept.id}> <td>{dept.name || dept.id}</td> <td> <Button variant='primary' size='sm' onClick={() => handleEditClick(dept)} > Edit </Button> </td> </tr>; })} </tbody> </Table> {selectedDepartment && <DepartmentSettingsModal department={selectedDepartment} onClose={handleModalClose} onUpdate={handleUpdate} />} </>; } |