Skip to content

Commit 7402b23

Browse files
fix: capacity and assignment issue (#1055)
* Fix capacity and assignment issue * formatting * formatting * fix test cases --------- Co-authored-by: nikhila-aot <38471389+nikhila-aot@users.noreply.github.com>
1 parent 2ae8ccd commit 7402b23

File tree

7 files changed

+113
-190
lines changed

7 files changed

+113
-190
lines changed

backend/cats/src/app/services/staff/staff.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('StaffService', () => {
9393
id: 1,
9494
name: 'John Doe',
9595
assignments: 3,
96-
capacity: 10,
96+
capacity: 160,
9797
});
9898
expect(dataSourceMock.query).toHaveBeenCalledTimes(2);
9999
});

backend/cats/src/app/services/staff/staff.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class StaffService {
3232
try {
3333
this.loggerService.log('StaffService: getStaffs start');
3434

35-
const capacity = 10;
35+
const capacity = 160;
3636
const offset = (page - 1) * pageSize;
3737
let havingClause = '';
3838
const assignmentExpr = `

cats-frontend/src/app/features/applications/search/Search.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ const Search: React.FC<SearchProps> = ({ filterMyTasks = false }) => {
217217
isSelected: filter === Filter.Unassigned,
218218
},
219219
{
220-
label: 'Overcapacity',
221-
value: Filter.Overcapacity,
222-
onClick: () => handleFilterChange(Filter.Overcapacity),
223-
isSelected: filter === Filter.Overcapacity,
220+
label: 'Completed',
221+
value: Filter.Completed,
222+
onClick: () => handleFilterChange(Filter.Completed),
223+
isSelected: filter === Filter.Completed,
224224
},
225225
];
226226

cats-frontend/src/app/features/assignment/Assignment.tsx

Lines changed: 62 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,13 @@ import GetConfig from './StaffTableConfig';
77
import StaffTable from './StaffTable';
88
import { RequestStatus } from '../../helpers/requests/status';
99
import { useGetParticipantRolesQuery } from '../applications/application/applicationTabs/appParticipants/graphql/Participants.generated';
10-
1110
import {
1211
useGetAllActiveStaffMembersForApplicationServiceTypeQuery,
1312
useGetAllActiveStaffMembersQuery,
1413
useGetApplicationServiceTypesQuery,
1514
useGetStaffAssignedByAppIdQuery,
1615
useUpdateStaffAssignedMutation,
1716
} from './graphql/assignment.generated';
18-
import {
19-
UpdateDisplayTypeParams,
20-
updateTableColumn,
21-
} from '../../helpers/utility';
2217
import {
2318
CancelButton,
2419
SaveButton,
@@ -43,31 +38,17 @@ const Assignment: React.FC<AssignmentProps> = ({
4338
}) => {
4439
const [isMessageModalOpen, setIsMessageModalOpen] = useState(false);
4540
const [messageContent, setMessageContent] = useState('');
46-
47-
const applicationId = id ? Number(id) : 0;
48-
49-
const [roleList, setRoleList] = useState<any[]>([]);
50-
51-
const [serviceTypes, SetServiceTypes] = useState<any[]>([]);
52-
5341
const [assignmentServiceType, setAssignmentServiceType] =
5442
useState<string>('');
43+
const [staffRecords, setStaffRecords] = useState<any[]>([]);
5544

56-
const { staffColumnInternal } = GetConfig();
57-
58-
const [internalRow, setInternalRow] = useState(staffColumnInternal);
59-
45+
const applicationId = id ? Number(id) : 0;
6046
const { data: rolesData } = useGetParticipantRolesQuery();
61-
62-
const {
63-
data: staffMemebersList,
64-
loading: staffMemebersLoading,
65-
refetch: staffMemebersRefetch,
66-
} = useGetAllActiveStaffMembersQuery();
47+
const { data: staffMemebersList, refetch: staffMemebersRefetch } =
48+
useGetAllActiveStaffMembersQuery();
6749

6850
const {
6951
data: staffMemebersListForServiceType,
70-
loading: staffMemebersLoadingForServiceType,
7152
refetch: staffMemebersRefetchForServiceType,
7253
} = useGetAllActiveStaffMembersForApplicationServiceTypeQuery({
7354
variables: {
@@ -77,26 +58,7 @@ const Assignment: React.FC<AssignmentProps> = ({
7758
},
7859
});
7960

80-
useEffect(() => {
81-
if (assignmentServiceType) {
82-
staffMemebersRefetchForServiceType({
83-
applicationServiceTypeId: Number(assignmentServiceType),
84-
});
85-
}
86-
}, [assignmentServiceType]);
87-
88-
useEffect(() => {
89-
if (staffMemebersListForServiceType) {
90-
processStaffMemebersList(
91-
staffMemebersList?.getAllActiveStaffMembers?.data || [],
92-
staffMemebersListForServiceType
93-
?.getAllActiveStaffMembersForApplicationServiceType?.data || [],
94-
);
95-
}
96-
}, [staffMemebersListForServiceType]);
97-
9861
const { data: serviceTypesList } = useGetApplicationServiceTypesQuery();
99-
10062
const [updateStaffAssigned] = useUpdateStaffAssignedMutation();
10163

10264
const { data: applicationData, loading: applicationDataLoading } =
@@ -120,22 +82,63 @@ const Assignment: React.FC<AssignmentProps> = ({
12082
skip: !application?.siteId,
12183
});
12284

123-
useEffect(() => {
124-
SetServiceTypes(serviceTypesList?.getApplicationServiceTypes?.data || []);
125-
}, [serviceTypesList]);
126-
127-
useEffect(() => {
128-
setRoleList(rolesData?.getAllParticipantRoles?.data || []);
129-
}, [rolesData]);
130-
131-
const [staffRecords, setStaffRecords] = useState<any[]>([]);
132-
13385
const {
13486
data: staffData,
13587
loading: dataLoading,
13688
refetch: staffRefetch,
13789
} = useGetStaffAssignedByAppIdQuery({ variables: { applicationId } });
13890

91+
const [searchParam, setSearchParam] = useState('');
92+
const { staffColumnInternal } = GetConfig({
93+
setSearchParam,
94+
options: staffMemebersList?.getAllActiveStaffMembers?.data?.map(
95+
(item: any) => ({
96+
key: item.personId.toString(),
97+
value: item.personFullName,
98+
}),
99+
) as [{ key: string; value: string }],
100+
filteredOptions:
101+
staffMemebersListForServiceType?.getAllActiveStaffMembersForApplicationServiceType?.data
102+
?.filter(
103+
(item: any) =>
104+
!staffRecords
105+
?.map((item) => item.personId)
106+
?.includes(item.personId),
107+
)
108+
?.filter((item: any) =>
109+
item.personFullName
110+
.toLowerCase()
111+
.includes(searchParam?.trim()?.toLowerCase()),
112+
)
113+
.map((item: any) => ({
114+
key: item.personId.toString(),
115+
value:
116+
item.personFullName +
117+
' - (' +
118+
((item.currentCapacity / 160) * 100).toFixed(2) +
119+
'%)',
120+
})) as [{ key: string; value: string }],
121+
rolesOptions: rolesData?.getAllParticipantRoles?.data
122+
?.filter(
123+
(item: any) =>
124+
item.description === 'Caseworker' ||
125+
item.description === 'Statutory Decision Maker' ||
126+
item.description === 'Mentor',
127+
)
128+
?.map((item: any) => ({
129+
key: item.id,
130+
value: item.description,
131+
})) as [{ key: string; value: string }],
132+
});
133+
134+
useEffect(() => {
135+
if (assignmentServiceType) {
136+
staffMemebersRefetchForServiceType({
137+
applicationServiceTypeId: Number(assignmentServiceType),
138+
});
139+
}
140+
}, [assignmentServiceType]);
141+
139142
useEffect(() => {
140143
setStaffRecords(staffData?.getStaffAssignedByAppId?.data?.staffList || []);
141144
let tempServiceType =
@@ -219,122 +222,11 @@ const Assignment: React.FC<AssignmentProps> = ({
219222
});
220223
};
221224

222-
// Handle search action
223-
const handleSearch = (
224-
value: any,
225-
staffMemebersArray: any,
226-
staffMemberArrayForServieType: any,
227-
) => {
228-
let existingStaffIds = staffRecords.map((item) => item.personId);
229-
value.trim();
230-
231-
setInternalRow((prev) =>
232-
updateTableColumn(prev, {
233-
indexToUpdate: prev.findIndex(
234-
(item) => item.displayType?.graphQLPropertyName === 'personId',
235-
),
236-
updates: {
237-
isLoading: RequestStatus.success,
238-
filteredOptions: staffMemberArrayForServieType
239-
?.filter((item: any) => !existingStaffIds.includes(item.personId))
240-
?.filter((item: any) =>
241-
item.personFullName.toLowerCase().includes(value.toLowerCase()),
242-
)
243-
.map((item: any) => ({
244-
key: item.personId.toString(),
245-
value:
246-
item.personFullName +
247-
' - (' +
248-
((item.currentCapacity / 160) * 100).toFixed(2) +
249-
'%)',
250-
})),
251-
handleSearch: (term: any) =>
252-
handleSearch(
253-
term,
254-
staffMemebersArray,
255-
staffMemberArrayForServieType,
256-
),
257-
customInfoMessage: <></>,
258-
},
259-
}),
260-
);
261-
};
262-
263-
const processStaffMemebersList = (
264-
staffMemebersList: any,
265-
staffMemberArrayForServieType: any,
266-
) => {
267-
if (!staffMemebersList) {
268-
return false;
269-
}
270-
let options = staffMemebersList.map((item: any) => ({
271-
key: item.personId.toString(),
272-
value: item.personFullName,
273-
}));
274-
275-
let params: UpdateDisplayTypeParams = {
276-
indexToUpdate: staffColumnInternal.findIndex(
277-
(item) => item.displayType?.graphQLPropertyName === 'personId',
278-
),
279-
updates: {
280-
isLoading: RequestStatus.success,
281-
options: options,
282-
filteredOptions: options,
283-
handleSearch: (term: string) =>
284-
handleSearch(term, staffMemebersList, staffMemberArrayForServieType),
285-
customInfoMessage: <></>,
286-
},
287-
};
288-
setInternalRow(updateTableColumn(internalRow, params));
289-
};
290-
291-
useEffect(() => {
292-
processStaffMemebersList(
293-
staffMemebersList?.getAllActiveStaffMembers?.data || [],
294-
staffMemebersListForServiceType
295-
?.getAllActiveStaffMembersForApplicationServiceType?.data || [],
296-
);
297-
}, [staffMemebersLoading, staffMemebersLoadingForServiceType]);
298-
299225
useEffect(() => {
300226
staffMemebersRefetch();
301227
staffRefetch({ applicationId: applicationId });
302228
}, []);
303229

304-
useEffect(() => {
305-
let uniqueRoles = roleList.map((item: any) => ({
306-
key: item.id,
307-
value: item.description,
308-
}));
309-
310-
uniqueRoles = uniqueRoles.filter(
311-
(item: any) =>
312-
item.value === 'Caseworker' ||
313-
item.value === 'Statutory Decision Maker' ||
314-
item.value === 'Mentor',
315-
);
316-
317-
let params: UpdateDisplayTypeParams = {
318-
indexToUpdate: staffColumnInternal.findIndex(
319-
(item) => item.displayType?.graphQLPropertyName === 'roleId',
320-
),
321-
updates: {
322-
isLoading: RequestStatus.success,
323-
options: uniqueRoles,
324-
filteredOptions: uniqueRoles,
325-
handleSearch: (term: string) =>
326-
handleSearch(
327-
term,
328-
staffMemebersList?.getAllActiveStaffMembers?.data || [],
329-
staffMemebersListForServiceType
330-
?.getAllActiveStaffMembersForApplicationServiceType?.data || [],
331-
),
332-
customInfoMessage: <></>,
333-
},
334-
};
335-
setInternalRow(updateTableColumn(internalRow, params));
336-
}, [roleList]);
337-
338230
return (
339231
<div role="assign staff" className="assign-section">
340232
<Details
@@ -385,10 +277,12 @@ const Assignment: React.FC<AssignmentProps> = ({
385277
label={'Application Service Type'}
386278
customLabelCss={''}
387279
placeholder={'Select Service Type'}
388-
options={serviceTypes.map((item) => ({
389-
key: item.key,
390-
value: item.value,
391-
}))}
280+
options={serviceTypesList?.getApplicationServiceTypes?.data?.map(
281+
(item) => ({
282+
key: item.key,
283+
value: item.value,
284+
}),
285+
)}
392286
customInputTextCss="panelLabel"
393287
value={assignmentServiceType}
394288
onChange={(value) => {
@@ -450,7 +344,7 @@ const Assignment: React.FC<AssignmentProps> = ({
450344
}
451345
}}
452346
handleWidgetCheckBox={() => {}}
453-
tableColumnConfig={internalRow}
347+
tableColumnConfig={staffColumnInternal}
454348
formData={staffRecords.filter((item) => item.action !== 'remove')}
455349
status={RequestStatus.success}
456350
handleTableSort={() => {}}

cats-frontend/src/app/features/assignment/StaffTableConfig.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1-
import {
2-
CircleExclamation,
3-
ExclamationTriangleIcon,
4-
XmarkIcon,
5-
} from '../../components/common/icon';
1+
import { XmarkIcon } from '../../components/common/icon';
62
import { FormFieldType } from '../../components/input-controls/IFormField';
73
import { ColumnSize, TableColumn } from '../../components/table/TableColumn';
84
import { RequestStatus } from '../../helpers/requests/status';
95
import CustomProgressBar from '../../components/progress-bar/progressBar';
106

11-
export const GetConfig = () => {
7+
export const GetConfig = ({
8+
setSearchParam,
9+
options,
10+
filteredOptions,
11+
rolesOptions,
12+
}: {
13+
setSearchParam: (term: string) => void;
14+
options: [{ key: string; value: string }] | undefined;
15+
filteredOptions: [{ key: string; value: string }] | undefined;
16+
rolesOptions: [{ key: string; value: string }] | undefined;
17+
}) => {
1218
const staffColumnInternal: TableColumn[] = [
1319
{
1420
id: 1,
@@ -24,8 +30,6 @@ export const GetConfig = () => {
2430
placeholder: 'Search Staff',
2531
isLoading: RequestStatus.idle,
2632
value: '',
27-
options: [],
28-
filteredOptions: [],
2933
colSize: 'col-lg-6 col-md-6 col-sm-12',
3034
customLabelCss: 'custom-participant-lbl-text',
3135
customInputTextCss: 'custom-participant-input-text',
@@ -34,7 +38,9 @@ export const GetConfig = () => {
3438
customPlaceholderCss: 'custom-participant-search-placeholder',
3539
customMenuMessage: <span>Please select site participant name:</span>,
3640
tableMode: true,
37-
handleSearch: () => {},
41+
options: options || [],
42+
filteredOptions: filteredOptions || [],
43+
handleSearch: setSearchParam,
3844
validation: {
3945
required: true,
4046
customMessage: 'Staff Member is required.',
@@ -72,7 +78,7 @@ export const GetConfig = () => {
7278
graphQLPropertyName: 'roleId',
7379
placeholder: 'Select Role',
7480
value: '',
75-
options: [],
81+
options: rolesOptions || [],
7682
colSize: 'col-lg-6 col-md-6 col-sm-12',
7783
customLabelCss: 'custom-participant-lbl-text',
7884
customInputTextCss: 'custom-participant-input-text',

0 commit comments

Comments
 (0)