Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated the User Management Design #9954

Merged
merged 30 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c175797
updated the user management design
AdityaJ2305 Jan 14, 2025
68ed9ba
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 14, 2025
16145f2
fix the small screen crash
AdityaJ2305 Jan 14, 2025
b789369
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 14, 2025
ada30bb
minor changes
AdityaJ2305 Jan 14, 2025
d8fda8c
Merge branch 'userList_design_update' of https://github.com/AdityaJ23…
AdityaJ2305 Jan 14, 2025
c1e3bc2
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 14, 2025
26ee976
coderabbit suggestion
AdityaJ2305 Jan 14, 2025
04d7899
Merge branch 'userList_design_update' of https://github.com/AdityaJ23…
AdityaJ2305 Jan 14, 2025
57db8e6
added skeleton view specific
AdityaJ2305 Jan 14, 2025
d801e1c
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 14, 2025
4bf5ff4
descriptive name
AdityaJ2305 Jan 14, 2025
bcdb66b
Merge branch 'userList_design_update' of https://github.com/AdityaJ23…
AdityaJ2305 Jan 14, 2025
e3a0c5d
nitpick sugg
AdityaJ2305 Jan 14, 2025
41b4cc5
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 14, 2025
8744d7c
coderabbit suggestion
AdityaJ2305 Jan 14, 2025
77324c5
coderabbit suggestion
AdityaJ2305 Jan 14, 2025
4204f63
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
a8dfcca
minor changes sugg by jeevan
AdityaJ2305 Jan 15, 2025
8b5ff83
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
0292a70
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
af5f017
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
783215a
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
0d7f6d9
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
4db7098
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 15, 2025
238411e
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 16, 2025
090bd1c
inline fix
AdityaJ2305 Jan 16, 2025
7ef0ea2
Merge branch 'userList_design_update' of https://github.com/AdityaJ23…
AdityaJ2305 Jan 16, 2025
33eb111
Merge branch 'develop' into userList_design_update
AdityaJ2305 Jan 16, 2025
c79b915
changed to 15 limit
AdityaJ2305 Jan 16, 2025
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
1 change: 1 addition & 0 deletions public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2118,6 +2118,7 @@
"username_userdetails_not_found": "Unable to fetch details as username or user details not found",
"username_valid": "Username is valid",
"users": "Users",
"users_management": "Users Management",
"vacant": "Vacant",
"vaccinated": "Vaccinated",
"vaccine_name": "Vaccine name",
Expand Down
115 changes: 70 additions & 45 deletions src/components/Facility/FacilityUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,51 @@ import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import { useTranslation } from "react-i18next";

import CountBlock from "@/CAREUI/display/Count";
import CareIcon from "@/CAREUI/icons/CareIcon";

import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";

import Page from "@/components/Common/Page";
import UserListView from "@/components/Users/UserListAndCard";

import useFilters from "@/hooks/useFilters";

import { RESULTS_PER_PAGE_LIMIT } from "@/common/constants";

import routes from "@/Utils/request/api";
import query from "@/Utils/request/query";

export default function FacilityUsers(props: { facilityId: string }) {
const { t } = useTranslation();
const { qParams, updateQuery, Pagination } = useFilters({
limit: 18,
limit: RESULTS_PER_PAGE_LIMIT,
AdityaJ2305 marked this conversation as resolved.
Show resolved Hide resolved
cacheBlacklist: ["username"],
});
const [activeTab, setActiveTab] = useState(0);
const [activeTab, setActiveTab] = useState<"card" | "list">("card");
const { facilityId } = props;

let usersList: JSX.Element = <></>;

const { data: userListData, isLoading: userListLoading } = useQuery({
queryKey: ["facilityUsers", facilityId],
queryFn: query(routes.facility.getUsers, {
pathParams: { facility_id: facilityId },
queryKey: ["facilityUsers", facilityId, qParams],
queryFn: query.debounced(routes.facility.getUsers, {
pathParams: { facility_id: facilityId.toString() },
AdityaJ2305 marked this conversation as resolved.
Show resolved Hide resolved
queryParams: {
username: qParams.username,
limit: qParams.limit,
offset: (qParams.page - 1) * qParams.limit,
},
}),
enabled: !!facilityId,
});

if (userListLoading) {
return (
<div className="px-6">
<Skeleton className="h-8 w-32 mb-4" />
<div className="flex items-center mb-4">
<Skeleton className="h-16 w-16 rounded-lg mr-3" />
<div>
<Skeleton className="h-4 w-14 mb-1" />
<Skeleton className="h-12 w-8" />
</div>
</div>
<div className="flex items-center justify-between mb-4">
<Skeleton className="h-10 w-72" />
<div className="flex space-x-2">
<Skeleton className="h-10 w-32" />
<Skeleton className="h-10 w-32" />
</div>
</div>
if (userListLoading || !userListData) {
usersList = (
<div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-4">
{Array.from({ length: 6 }).map((_, i) => (
<Card key={i}>
Expand All @@ -76,30 +73,58 @@ export default function FacilityUsers(props: { facilityId: string }) {
</div>
</div>
);
}
if (!userListData) {
return <div>{t("no_users_found")}</div>;
} else {
usersList = (
<div>
<UserListView
users={userListData?.results ?? []}
activeTab={activeTab}
/>
<Pagination totalCount={userListData.count} />
</div>
);
}

return (
<Page title={t("users")} hideBack={true} breadcrumbs={false}>
<CountBlock
text={t("total_users")}
count={userListData.count}
loading={userListLoading}
icon="d-people"
className="my-3 flex flex-col items-center sm:items-start"
/>

<UserListView
users={userListData?.results ?? []}
onSearch={(username) => updateQuery({ username })}
searchValue={qParams.username}
activeTab={activeTab}
onTabChange={setActiveTab}
/>

<Pagination totalCount={userListData.count} />
<Page title={t("users_management")}>
<Badge
className="bg-purple-50 text-purple-700 ml-2 text-sm font-medium rounded-xl px-3 m-3"
variant="outline"
>
{`${userListData ? userListData.count : ""} Users`}
AdityaJ2305 marked this conversation as resolved.
Show resolved Hide resolved
</Badge>
<hr className="mt-4"></hr>
<div className="flex items-center justify-between gap-4 m-5 ml-0">
<Input
id="search-by-username"
name="username"
onChange={(e) => updateQuery({ username: e.target.value })}
value={qParams.username}
placeholder={t("search_by_username")}
className="w-full max-w-sm"
/>
<Tabs
value={activeTab}
onValueChange={(value) => setActiveTab(value as "card" | "list")}
className="ml-auto"
>
<TabsList className="flex">
<TabsTrigger value="card" id="user-card-view">
<div className="flex items-center gap-2">
<CareIcon icon="l-credit-card" className="text-lg" />
<span>{t("card")}</span>
</div>
</TabsTrigger>
<TabsTrigger value="list" id="user-list-view">
<div className="flex items-center gap-2">
<CareIcon icon="l-list-ul" className="text-lg" />
<span>{t("list")}</span>
</div>
</TabsTrigger>
</TabsList>
</Tabs>
</div>
<div>{usersList}</div>
</Page>
);
}
68 changes: 13 additions & 55 deletions src/components/Users/UserListAndCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import CareIcon from "@/CAREUI/icons/CareIcon";
import { Badge } from "@/components/ui/badge";

import { Avatar } from "@/components/Common/Avatar";
import Tabs from "@/components/Common/Tabs";
import SearchInput from "@/components/Form/SearchInput";

import useAuthUser from "@/hooks/useAuthUser";
import useSlug from "@/hooks/useSlug";
Expand Down Expand Up @@ -102,7 +100,6 @@ export const UserStatusIndicator = ({
);
};
const UserCard = ({ user }: { user: UserBase }) => {
const userOnline = isUserOnline(user);
const { width } = useWindowDimensions();
const mediumScreenBreakpoint = 640;
const isMediumScreen = width <= mediumScreenBreakpoint;
Expand All @@ -126,7 +123,7 @@ const UserCard = ({ user }: { user: UserBase }) => {
name={formatName(user)}
className="h-16 w-16 self-center text-2xl sm:self-auto"
/>
{isMediumScreen && getNameAndStatusCard(user, userOnline)}
{isMediumScreen && getNameAndStatusCard(user, false)}
</div>
<div className="flex flex-col w-full">
{!isMediumScreen &&
Expand All @@ -135,7 +132,15 @@ const UserCard = ({ user }: { user: UserBase }) => {
<div className="text-sm">
<div className="text-gray-500">{t("role")}</div>
<div id="role" className="font-medium">
{user.user_type}
{user.user_type ? user.user_type : "-"}
</div>
</div>
<div className="text-sm">
<div className="text-gray-500">{t("contact_number")}</div>
<div id="contact" className="font-medium">
{user.phone_number
? formatPhoneNumber(user.phone_number)
: "-"}
</div>
</div>
</div>
Expand Down Expand Up @@ -238,64 +243,17 @@ export const UserList = ({ users }: { users?: UserBase[] }) => {
};
interface UserListViewProps {
users: UserBase[];
onSearch: (username: string) => void;
searchValue: string;
activeTab: number;
onTabChange: (tab: number) => void;
activeTab: string;
}

export default function UserListView({
users,
onSearch,
searchValue,
activeTab,
onTabChange,
}: UserListViewProps) {
export default function UserListView({ users, activeTab }: UserListViewProps) {
const { t } = useTranslation();

return (
<>
<div className="mb-4 flex flex-col items-center justify-between gap-3 sm:flex-row">
<div className="sm:w-1/2">
<SearchInput
id="search-by-username"
name="username"
onChange={(e) => onSearch(e.value)}
value={searchValue}
placeholder={t("search_by_username")}
/>
</div>
<Tabs
tabs={[
{
text: (
<div className="flex items-center gap-2">
<CareIcon icon="l-credit-card" className="text-lg" />
<span>{t("card")}</span>
</div>
),
value: 0,
id: "user-card-view",
},
{
text: (
<div className="flex items-center gap-2">
<CareIcon icon="l-list-ul" className="text-lg" />
<span>{t("list")}</span>
</div>
),
value: 1,
id: "user-list-view",
},
]}
currentTab={activeTab}
onTabChange={(tab) => onTabChange(tab as number)}
className="float-right"
/>
</div>
{users.length > 0 ? (
<>
{activeTab === 0 ? (
{activeTab === "card" ? (
<UserGrid users={users} />
) : (
<UserList users={users} />
Expand Down
Loading