Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 57 additions & 32 deletions src/components/Users/UserDepartmentsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import CareIcon from "@/CAREUI/icons/CareIcon";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";

import { CardGridSkeleton } from "@/components/Common/SkeletonLoading";

import { userChildProps } from "@/components/Common/UserColumns";
import LinkUserToDepartmentSheet from "@/components/Users/LinkUserToDepartmentSheet";

import query from "@/Utils/request/query";
import useFilters from "@/hooks/useFilters";
import EditFacilityUserRoleSheet from "@/pages/Facility/settings/organizations/components/EditFacilityUserRoleSheet";
import useCurrentFacility from "@/pages/Facility/utils/useCurrentFacility";
import {
Expand Down Expand Up @@ -113,31 +115,32 @@ function DepartmentCard({
export default function UserDepartmentsTab({ userData }: userChildProps) {
const { t } = useTranslation();
const { facilityId } = useCurrentFacility();
const { qParams, updateQuery, Pagination, resultsPerPage } = useFilters({
limit: 15,
disableCache: true,
});

const { data: departmentsData, isLoading } = useQuery({
queryKey: ["facilityOrganizations", "byUser", facilityId, userData.id],
queryFn: query(facilityOrganizationApi.list, {
queryKey: [
"facilityOrganizations",
"byUser",
facilityId,
userData.id,
qParams,
resultsPerPage,
],
Comment thread
rithviknishad marked this conversation as resolved.
queryFn: query.debounced(facilityOrganizationApi.list, {
pathParams: { facilityId: facilityId! },
queryParams: {
containing_user: userData.id,
name: qParams.name || undefined,
limit: resultsPerPage,
offset: ((qParams.page || 1) - 1) * resultsPerPage,
},
Comment thread
Jacobjeevan marked this conversation as resolved.
}),
enabled: !!facilityId,
});

if (isLoading) {
return (
<div className="mt-8 space-y-4">
<h3 className="text-lg font-semibold text-gray-900 mb-4">
{t("departments")}
</h3>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<CardGridSkeleton count={6} />
</div>
</div>
);
}

const departments = departmentsData?.results ?? [];

return (
Expand All @@ -151,27 +154,49 @@ export default function UserDepartmentsTab({ userData }: userChildProps) {
facilityId={facilityId}
/>
</div>

{departments.length === 0 ? (
<Input
placeholder={t("search_departments_placeholder")}
aria-label={t("search_departments_placeholder")}
value={qParams.name || ""}
onChange={(e) => updateQuery({ name: e.target.value || undefined })}
className="w-full max-w-sm"
/>
Comment thread
Jacobjeevan marked this conversation as resolved.

{isLoading ? (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<CardGridSkeleton count={6} />
</div>
) : departments.length === 0 ? (
<div className="flex flex-col items-center justify-center py-12 border border-dashed border-gray-300 rounded-lg">
<CareIcon icon="l-building" className="h-16 w-16 text-gray-400" />
<p className="mt-4 text-lg font-medium text-gray-600">
{t("no_departments_assigned")}
</p>
<p className="mt-2 text-sm text-gray-500">
{t("click_link_department_to_get_started")}
</p>
{qParams.name ? (
<p className="mt-4 text-lg font-medium text-gray-600">
{t("no_departments_found")}
</p>
) : (
<>
<p className="mt-4 text-lg font-medium text-gray-600">
{t("no_departments_assigned")}
</p>
<p className="mt-2 text-sm text-gray-500">
{t("click_link_department_to_get_started")}
</p>
</>
)}
</div>
) : (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{departments.map((department) => (
<DepartmentCard
key={department.id}
department={department}
userData={userData}
facilityId={facilityId}
/>
))}
<div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{departments.map((department) => (
<DepartmentCard
key={department.id}
department={department}
userData={userData}
facilityId={facilityId}
/>
))}
</div>
<Pagination totalCount={departmentsData?.count ?? 0} />
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ export default function EditUserRoleSheet({
}: Props) {
const queryClient = useQueryClient();
const [open, setOpen] = useState(false);
const [selectedRole, setSelectedRole] = useState<RoleBase>();
const [selectedRole, setSelectedRole] = useState<RoleBase>({
...userRole.role,
});
Comment on lines +43 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Stale selection persists across sheet open/close cycles

useState initializes selectedRole only once when the component mounts. Because this component lives permanently in the DOM inside each rendered DepartmentCard, the selectedRole state is never reset between opens. If a user selects a different role, cancels without saving, then reopens the sheet, they will see the previously-chosen (but unsaved) role pre-selected — which is misleading and would cause an unintended role change if they then click "Update Role". Add a useEffect that resets to userRole.role whenever open transitions to true.

const [showRemoveDialog, setShowRemoveDialog] = useState(false);
Comment thread
Jacobjeevan marked this conversation as resolved.
const { t } = useTranslation();

Expand Down
Loading