diff --git a/src/Components/Users/ManageUsers.tsx b/src/Components/Users/ManageUsers.tsx index 1a39b57ec53..6df7467d0f3 100644 --- a/src/Components/Users/ManageUsers.tsx +++ b/src/Components/Users/ManageUsers.tsx @@ -1,41 +1,44 @@ -import * as Notification from "../../Utils/Notifications.js"; +import dayjs from "dayjs"; +import { navigate } from "raviger"; import { lazy, useState } from "react"; -import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover"; -import ButtonV2, { Submit } from "../Common/components/ButtonV2"; -import CareIcon from "../../CAREUI/icons/CareIcon"; -import ConfirmHomeFacilityUpdateDialog from "./ConfirmHomeFacilityUpdateDialog"; +import { useTranslation } from "react-i18next"; import CountBlock from "../../CAREUI/display/Count"; -import { FacilityModel } from "../Facility/models"; -import { FacilitySelect } from "../Common/FacilitySelect"; -import SearchInput from "../Form/SearchInput"; -import SkillsSlideOver from "./SkillsSlideOver"; +import CareIcon from "../../CAREUI/icons/CareIcon"; +import { AdvancedFilterButton } from "../../CAREUI/interactive/FiltersSlideover"; import SlideOverCustom from "../../CAREUI/interactive/SlideOver"; import { USER_TYPES } from "../../Common/constants"; -import UnlinkFacilityDialog from "./UnlinkFacilityDialog"; -import UserDeleteDialog from "./UserDeleteDialog"; -import UserDetails from "../Common/UserDetails"; -import UserFilter from "./UserFilter"; +import useAuthUser from "../../Common/hooks/useAuthUser.js"; +import useFilters from "../../Common/hooks/useFilters"; +import useWindowDimensions from "../../Common/hooks/useWindowDimensions"; +import routes from "../../Redux/api.js"; +import * as Notification from "../../Utils/Notifications.js"; +import request from "../../Utils/request/request.js"; +import useQuery from "../../Utils/request/useQuery.js"; import { classNames, isUserOnline, relativeTime, showUserDelete, } from "../../Utils/utils"; -import { navigate } from "raviger"; -import useFilters from "../../Common/hooks/useFilters"; -import useWindowDimensions from "../../Common/hooks/useWindowDimensions"; +import { FacilitySelect } from "../Common/FacilitySelect"; +import Pagination from "../Common/Pagination"; +import UserDetails from "../Common/UserDetails"; +import ButtonV2, { Submit } from "../Common/components/ButtonV2"; import CircularProgress from "../Common/components/CircularProgress.js"; import Page from "../Common/components/Page.js"; -import dayjs from "dayjs"; +import { FacilityModel } from "../Facility/models"; import TextFormField from "../Form/FormFields/TextFormField.js"; -import useAuthUser from "../../Common/hooks/useAuthUser.js"; -import routes from "../../Redux/api.js"; -import useQuery from "../../Utils/request/useQuery.js"; -import request from "../../Utils/request/request.js"; +import SearchInput from "../Form/SearchInput"; +import ConfirmHomeFacilityUpdateDialog from "./ConfirmHomeFacilityUpdateDialog"; +import SkillsSlideOver from "./SkillsSlideOver"; +import UnlinkFacilityDialog from "./UnlinkFacilityDialog"; +import UserDeleteDialog from "./UserDeleteDialog"; +import UserFilter from "./UserFilter"; const Loading = lazy(() => import("../Common/Loading")); export default function ManageUsers() { + const { t } = useTranslation(); const { width } = useWindowDimensions(); const { qParams, @@ -107,7 +110,7 @@ export default function ManageUsers() { onClick={() => navigate("/users/add")} > -

Add New User

+

{t("add_new_user")}

); @@ -432,13 +435,13 @@ export default function ManageUsers() { } else if (userListData?.results && userListData?.results.length === 0) { manageUsers = (
-
No Users Found
+
{t("no_users_found")}
); } return ( - + {expandSkillList && ( { - //fetchData({ aborted: false }); - }} > @@ -466,12 +466,12 @@ export default function ManageUsers() { setWeeklyHoursError(""); }} slideFrom="right" - title="Average weekly working hours" + title={t("average_weekly_working_hours")} dialogClass="md:w-[400px]" >
- Set Average weekly working hours for {selectedUser} + {t("set_average_weekly_working_hours_for")} {selectedUser}
- +
@@ -508,7 +508,7 @@ export default function ManageUsers() { name="username" onChange={(e) => updateQuery({ [e.name]: e.value })} value={qParams.username} - placeholder="Search by username" + placeholder={t("search_by_username")} />
@@ -555,9 +555,14 @@ export default function ManageUsers() { } function UserFacilities(props: { user: any }) { + const { t } = useTranslation(); const { user } = props; const username = user.username; + const limit = 20; const [isLoading, setIsLoading] = useState(false); + const [currentPage, setCurrentPage] = useState(1); + const [offset, setOffset] = useState(0); + const [totalCount, setTotalCount] = useState(0); const [facility, setFacility] = useState(null); const [unlinkFacilityData, setUnlinkFacilityData] = useState<{ show: boolean; @@ -600,8 +605,23 @@ function UserFacilities(props: { user: any }) { refetch: refetchUserFacilities, } = useQuery(routes.userListFacility, { pathParams: { username }, + query: { + limit, + offset, + }, + onResponse: ({ res, data }) => { + if (res?.status === 200 && data) { + setTotalCount(data.count); + } + }, }); + const handlePagination = (page: number, limit: number) => { + const offset = (page - 1) * limit; + setCurrentPage(page); + setOffset(offset); + }; + const updateHomeFacility = async (username: string, facility: any) => { setIsLoading(true); const { res } = await request(routes.partialUpdateUser, { @@ -676,7 +696,7 @@ function UserFacilities(props: { user: any }) { className="mt-1 h-[45px] w-[74px] text-base" onClick={() => addFacility(username, facility)} > - Add + {t("add")}
{isLoading || userFacilitiesLoading ? ( @@ -688,7 +708,9 @@ function UserFacilities(props: { user: any }) { {/* Home Facility section */} {user?.home_facility_object && (
-
Home Facility
+
+ {t("home_facility")} +
{user?.home_facility_object?.name} @@ -706,7 +728,7 @@ function UserFacilities(props: { user: any }) { > - Clear Home Facility + {t("clear_home_facility")}
@@ -717,77 +739,90 @@ function UserFacilities(props: { user: any }) { )} {/* Linked Facilities section */} - {!!userFacilities?.length && ( + {!!userFacilities?.results.length && (
- Linked Facilities + {t("linked_facilities")}
- {userFacilities.map((facility: any, i: number) => { - if (user?.home_facility_object?.id === facility.id) { - // skip if it's a home facility - return null; - } - return ( -
-
- {facility.name} -
- + - + > + + + Unlink Facility + + +
-
- ); - })} + ); + } + )}
+ {totalCount > limit && ( +
+ +
+ )}
)} - {!user?.home_facility_object && !userFacilities?.length && ( + {!user?.home_facility_object && !userFacilities?.results.length && (

- No Linked Facilities + {t("no_linked_facilities")}

)} diff --git a/src/Locale/en/Users.json b/src/Locale/en/Users.json new file mode 100644 index 00000000000..515c77848b4 --- /dev/null +++ b/src/Locale/en/Users.json @@ -0,0 +1,13 @@ +{ + "user_management": "User Management", + "facilities": "Facilities", + "add_new_user": "Add New User", + "no_users_found": "No Users Found", + "home_facility": "Home Facility", + "clear_home_facility": "Clear Home Facility", + "linked_facilities": "Linked Facilities", + "no_linked_facilities": "No Linked Facilities", + "average_weekly_working_hours": "Average weekly working hours", + "set_average_weekly_working_hours_for": "Set Average weekly working hours for", + "search_by_username": "Search by username" +} \ No newline at end of file diff --git a/src/Locale/en/index.js b/src/Locale/en/index.js index 781ce97b009..d67138440cd 100644 --- a/src/Locale/en/index.js +++ b/src/Locale/en/index.js @@ -1,20 +1,21 @@ -import Auth from "./Auth.json"; import Asset from "./Asset.json"; +import Auth from "./Auth.json"; +import Bed from "./Bed.json"; import Common from "./Common.json"; import Consultation from "./Consultation.json"; +import CoverImageEdit from "./CoverImageEdit.json"; +import Diagnosis from "./Diagnosis.json"; import Entities from "./Entities.json"; +import ErrorPages from "./ErrorPages.json"; +import ExternalResult from "./ExternalResult.json"; import Facility from "./Facility.json"; import Hub from "./Hub.json"; -import ErrorPages from "./ErrorPages.json"; -import Shifting from "./Shifting.json"; +import Medicine from "./Medicine.json"; import Notifications from "./Notifications.json"; -import ExternalResult from "./ExternalResult.json"; -import CoverImageEdit from "./CoverImageEdit.json"; import Resource from "./Resource.json"; +import Shifting from "./Shifting.json"; import SortOptions from "./SortOptions.json"; -import Bed from "./Bed.json"; -import Medicine from "./Medicine.json"; -import Diagnosis from "./Diagnosis.json"; +import Users from "./Users.json"; export default { ...Auth, @@ -33,5 +34,6 @@ export default { ...Resource, ...Shifting, ...Bed, + ...Users, SortOptions, }; diff --git a/src/Redux/api.tsx b/src/Redux/api.tsx index 35a878adabc..5100a9fa35f 100644 --- a/src/Redux/api.tsx +++ b/src/Redux/api.tsx @@ -31,49 +31,47 @@ import { PatientAssetBed, } from "../Components/Assets/AssetTypes"; import { + IDeleteBedCapacity, + IDeleteExternalResult, + IExternalResult, + IExternalResultCsv, + ILocalBodies, + ILocalBodyByDistrict, + IPartialUpdateExternalResult, +} from "../Components/ExternalResult/models"; +import { + BedModel, CapacityModal, ConsultationModel, CreateBedBody, CurrentBed, - DistrictModel, DailyRoundsBody, DailyRoundsRes, + DistrictModel, DoctorModal, FacilityModel, + FacilityRequest, IFacilityNotificationRequest, IFacilityNotificationResponse, + InventoryItemsModel, + InventoryLogResponse, + InventorySummaryResponse, IUserFacilityRequest, LocalBodyModel, - PatientStatsModel, - FacilityRequest, - StateModel, - WardModel, LocationModel, - PatientNotesModel, - PatientNotesEditModel, - BedModel, MinimumQuantityItemResponse, - InventorySummaryResponse, - InventoryLogResponse, - InventoryItemsModel, + PatientNotesEditModel, + PatientNotesModel, + PatientStatsModel, PatientTransferResponse, + StateModel, + WardModel, } from "../Components/Facility/models"; -import { - IDeleteBedCapacity, - IDeleteExternalResult, - IExternalResult, - IExternalResultCsv, - ILocalBodies, - ILocalBodyByDistrict, - IPartialUpdateExternalResult, -} from "../Components/ExternalResult/models"; -import { - SkillModel, - SkillObjectModel, - UpdatePasswordForm, - UserModel, -} from "../Components/Users/models"; import { Prescription } from "../Components/Medicine/models"; +import { + NotificationData, + PNconfigData, +} from "../Components/Notifications/models"; import { CreateFileRequest, CreateFileResponse, @@ -83,22 +81,24 @@ import { SampleReportModel, SampleTestModel, } from "../Components/Patient/models"; -import { PaginatedResponse } from "../Utils/request/types"; import { - NotificationData, - PNconfigData, -} from "../Components/Notifications/models"; + SkillModel, + SkillObjectModel, + UpdatePasswordForm, + UserModel, +} from "../Components/Users/models"; +import { PaginatedResponse } from "../Utils/request/types"; -import { IComment, IResource } from "../Components/Resource/models"; -import { IShift } from "../Components/Shifting/models"; -import { HCXPolicyModel } from "../Components/HCX/models"; +import { ICD11DiagnosisModel } from "../Components/Diagnosis/types"; +import { EventGeneric } from "../Components/Facility/ConsultationDetails/Events/types"; import { InvestigationGroup, InvestigationType, } from "../Components/Facility/Investigations"; import { Investigation } from "../Components/Facility/Investigations/Reports/types"; -import { ICD11DiagnosisModel } from "../Components/Diagnosis/types"; -import { EventGeneric } from "../Components/Facility/ConsultationDetails/Events/types"; +import { HCXPolicyModel } from "../Components/HCX/models"; +import { IComment, IResource } from "../Components/Resource/models"; +import { IShift } from "../Components/Shifting/models"; /** * A fake function that returns an empty object casted to type T @@ -205,7 +205,7 @@ const routes = { userListFacility: { path: "/api/v1/users/{username}/get_facilities/", method: "GET", - TRes: Type(), + TRes: Type>(), }, addUserFacility: {