ENCOA-18: Improve the loading of the company names on the Group and Users lists

This commit is contained in:
Tiago Ribeiro
2024-04-18 16:03:09 +01:00
parent 771262fc18
commit 36b861266f
4 changed files with 90 additions and 28 deletions

View File

@@ -14,20 +14,30 @@ import {toast} from "react-toastify";
import readXlsxFile from "read-excel-file"; import readXlsxFile from "read-excel-file";
import {useFilePicker} from "use-file-picker"; import {useFilePicker} from "use-file-picker";
import {getUserCorporate} from "@/utils/groups"; import {getUserCorporate} from "@/utils/groups";
import { isAgentUser, isCorporateUser } from "@/resources/user";
const columnHelper = createColumnHelper<Group>(); const columnHelper = createColumnHelper<Group>();
const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/); const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/);
const LinkedCorporate = ({userId}: {userId: string}) => { const LinkedCorporate = ({userId, users, groups}: {userId: string, users: User[], groups: Group[]}) => {
const [companyName, setCompanyName] = useState(""); const [companyName, setCompanyName] = useState("");
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
useEffect(() => { useEffect(() => {
setIsLoading(true); const user = users.find((u) => u.id === userId)
getUserCorporate(userId) if (!user) return setCompanyName("")
.then((result) => setCompanyName(result?.corporateInformation?.companyInformation?.name || ""))
.finally(() => setIsLoading(false)); if (isCorporateUser(user)) return setCompanyName(user.corporateInformation?.companyInformation?.name || user.name)
}, [userId]); if (isAgentUser(user)) return setCompanyName(user.agentInformation?.companyName || user.name)
const belongingGroups = groups.filter((x) => x.participants.includes(userId))
const belongingGroupsAdmins = belongingGroups.map((x) => users.find((u) => u.id === x.admin)).filter((x) => !!x && isCorporateUser(x))
if (belongingGroupsAdmins.length === 0) return setCompanyName("")
const admin = (belongingGroupsAdmins[0] as CorporateUser)
setCompanyName(admin.corporateInformation?.companyInformation.name || admin.name)
}, [userId, users, groups]);
return isLoading ? <span className="animate-pulse">Loading...</span> : <>{companyName}</>; return isLoading ? <span className="animate-pulse">Loading...</span> : <>{companyName}</>;
}; };
@@ -224,7 +234,7 @@ export default function GroupList({user}: {user: User}) {
}), }),
columnHelper.accessor("admin", { columnHelper.accessor("admin", {
header: "Linked Corporate", header: "Linked Corporate",
cell: (info) => <LinkedCorporate userId={info.getValue()} />, cell: (info) => <LinkedCorporate userId={info.getValue()} users={users} groups={groups} />,
}), }),
columnHelper.accessor("participants", { columnHelper.accessor("participants", {
header: "Participants", header: "Participants",

View File

@@ -2,7 +2,7 @@ import Button from "@/components/Low/Button";
import {PERMISSIONS} from "@/constants/userPermissions"; import {PERMISSIONS} from "@/constants/userPermissions";
import useGroups from "@/hooks/useGroups"; import useGroups from "@/hooks/useGroups";
import useUsers from "@/hooks/useUsers"; import useUsers from "@/hooks/useUsers";
import {Type, User, userTypes, CorporateUser} from "@/interfaces/user"; import {Type, User, userTypes, CorporateUser, Group} from "@/interfaces/user";
import {Popover, Transition} from "@headlessui/react"; import {Popover, Transition} from "@headlessui/react";
import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table"; import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table";
import axios from "axios"; import axios from "axios";
@@ -44,16 +44,22 @@ const getCompanyName = async (user: User) => {
return ""; return "";
}; };
const CompanyNameCell = (user: User) => { const CompanyNameCell = ({users, user, groups}: {user: User, users: User[], groups: Group[]}) => {
const [companyName, setCompanyName] = useState(""); const [companyName, setCompanyName] = useState("");
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
useEffect(() => { useEffect(() => {
setIsLoading(true); if (isCorporateUser(user)) return setCompanyName(user.corporateInformation?.companyInformation?.name || user.name)
getCompanyName(user) if (isAgentUser(user)) return setCompanyName(user.agentInformation?.companyName || user.name)
.then((result) => setCompanyName(result))
.finally(() => setIsLoading(false)); const belongingGroups = groups.filter((x) => x.participants.includes(user.id))
}, [user]); const belongingGroupsAdmins = belongingGroups.map((x) => users.find((u) => u.id === x.admin)).filter((x) => !!x && isCorporateUser(x))
if (belongingGroupsAdmins.length === 0) return setCompanyName("")
const admin = (belongingGroupsAdmins[0] as CorporateUser)
setCompanyName(admin.corporateInformation?.companyInformation.name || admin.name)
}, [user, users, groups]);
return isLoading ? <span className="animate-pulse">Loading...</span> : <>{companyName}</>; return isLoading ? <span className="animate-pulse">Loading...</span> : <>{companyName}</>;
}; };
@@ -372,7 +378,7 @@ export default function UserList({user, filters = []}: {user: User; filters?: ((
<SorterArrow name="companyName" /> <SorterArrow name="companyName" />
</button> </button>
) as any, ) as any,
cell: (info) => <CompanyNameCell {...info.row.original} />, cell: (info) => <CompanyNameCell user={info.row.original} users={users} groups={groups} />,
}), }),
columnHelper.accessor("subscriptionExpirationDate", { columnHelper.accessor("subscriptionExpirationDate", {
header: ( header: (

View File

@@ -0,0 +1,29 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
import { app } from "@/firebase";
import {
getFirestore,
collection,
getDocs,
getDoc,
doc,
} from "firebase/firestore";
import { withIronSessionApiRoute } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
const db = getFirestore(app);
export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
res.status(401).json({ ok: false });
return;
}
const { id } = req.query as { id: string };
const snapshot = await getDoc(doc(db, "users", id));
if (!snapshot.exists()) return res.status(404).json({ ok: false });
res.status(200).json({ ...snapshot.data(), id: snapshot.id });
}

View File

@@ -1,20 +1,37 @@
import {CorporateUser, Group, User} from "@/interfaces/user"; import { CorporateUser, Group, User } from "@/interfaces/user";
import axios from "axios"; import axios from "axios";
export const isUserFromCorporate = async (userID: string) => { export const isUserFromCorporate = async (userID: string) => {
const groups = (await axios.get<Group[]>(`/api/groups?participant=${userID}`)).data; const groups = (await axios.get<Group[]>(`/api/groups?participant=${userID}`))
const users = (await axios.get<User[]>("/api/users/list")).data; .data;
const users = (await axios.get<User[]>("/api/users/list")).data;
const adminTypes = groups.map((g) => users.find((u) => u.id === g.admin)?.type); const adminTypes = groups.map(
return adminTypes.includes("corporate"); (g) => users.find((u) => u.id === g.admin)?.type,
);
return adminTypes.includes("corporate");
}; };
export const getUserCorporate = async (userID: string) => { export const getUserCorporate = async (
const users = (await axios.get<User[]>("/api/users/list")).data; userID: string,
if (users.find((u) => u.id === userID)?.type === "corporate") return users.find((u) => u.id === userID) as CorporateUser; ): Promise<CorporateUser | undefined> => {
const userRequest = await axios.get<User>(`/api/users/${userID}`);
if (userRequest.status === 200) {
const user = userRequest.data;
if (user.type === "corporate") return user;
}
const groups = (await axios.get<Group[]>(`/api/groups?participant=${userID}`)).data; const groups = (await axios.get<Group[]>(`/api/groups?participant=${userID}`))
.data;
const admins = groups.map((g) => users.find((u) => u.id === g.admin)).filter((x) => x?.type === "corporate"); const adminRequests = await Promise.all(
return admins.length > 0 ? (admins[0] as CorporateUser) : undefined; groups.map(async (g) => {
const userRequest = await axios.get<User>(`/api/users/${g.admin}`);
if (userRequest.status === 200) return userRequest.data;
return undefined;
}),
);
const admins = adminRequests.filter((x) => x?.type === "corporate");
return admins.length > 0 ? (admins[0] as CorporateUser) : undefined;
}; };