From c8be2f1255be8fd55b535c23063a8f7bfc662856 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 16:52:16 +0100 Subject: [PATCH 1/9] Prevented sessions from appearing when an assignment is done --- src/pages/api/sessions/index.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/pages/api/sessions/index.ts b/src/pages/api/sessions/index.ts index c5b30692..9b7fb3ec 100644 --- a/src/pages/api/sessions/index.ts +++ b/src/pages/api/sessions/index.ts @@ -4,6 +4,8 @@ import {app} from "@/firebase"; import {getFirestore, collection, getDocs, query, where, doc, setDoc, addDoc, getDoc} from "firebase/firestore"; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; +import {Session} from "@/hooks/useSessions"; +import moment from "moment"; const db = getFirestore(app); @@ -24,12 +26,17 @@ async function get(req: NextApiRequest, res: NextApiResponse) { const q = user ? query(collection(db, "sessions"), where("user", "==", user)) : collection(db, "sessions"); const snapshot = await getDocs(q); + const sessions = snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as Session[]; res.status(200).json( - snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })), + sessions.filter((x) => { + if (!x.assignment) return true; + if (x.assignment.results.filter((y) => y.user === user).length > 0) return false; + return moment().isAfter(moment(x.assignment.endDate)); + }), ); } From 3b43803b7e07f0d4c73dc1f2ed4122d2290998de Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 16:54:45 +0100 Subject: [PATCH 2/9] ENCOA-180: Prevented users from checking their results if not released yet --- src/components/Medium/StatGridItem.tsx | 6 +++++- src/exams/Finish.tsx | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Medium/StatGridItem.tsx b/src/components/Medium/StatGridItem.tsx index b0c3622b..c4c31040 100644 --- a/src/components/Medium/StatGridItem.tsx +++ b/src/components/Medium/StatGridItem.tsx @@ -277,7 +277,11 @@ const StatsGridItem: React.FC = ({ selectedTrainingExams.some((exam) => exam.includes(timestamp)) && "border-2 border-slate-600", )} - onClick={examNumber === undefined ? selectExam : undefined} + onClick={() => { + if (!!assignment && !assignment.released) return; + if (examNumber === undefined) return selectExam(); + return; + }} style={{ ...(width !== undefined && {width}), ...(height !== undefined && {height}), diff --git a/src/exams/Finish.tsx b/src/exams/Finish.tsx index d1f3d7a8..f8d5a5b4 100644 --- a/src/exams/Finish.tsx +++ b/src/exams/Finish.tsx @@ -212,7 +212,7 @@ export default function Finish({user, scores, modules, information, solutions, i )} - {assignment && !assignment.released && ( + {assignment && !assignment.released && !isLoading && (
{/* */} @@ -223,7 +223,7 @@ export default function Finish({user, scores, modules, information, solutions, i
)} - {!isLoading && ( + {!isLoading && !(assignment && !assignment.released) && (
{moduleResultText(selectedModule, bandScore)}
From ac980023b51c60d0f4e3ff7f3ad391f2343f3dab Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 16:59:39 +0100 Subject: [PATCH 3/9] Negated a simple change --- src/pages/api/sessions/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/api/sessions/index.ts b/src/pages/api/sessions/index.ts index 9b7fb3ec..16afdeca 100644 --- a/src/pages/api/sessions/index.ts +++ b/src/pages/api/sessions/index.ts @@ -35,7 +35,7 @@ async function get(req: NextApiRequest, res: NextApiResponse) { sessions.filter((x) => { if (!x.assignment) return true; if (x.assignment.results.filter((y) => y.user === user).length > 0) return false; - return moment().isAfter(moment(x.assignment.endDate)); + return !moment().isAfter(moment(x.assignment.endDate)); }), ); } From e312af36bbe308ea4bbe3e0e5bed10ddfaf27ad4 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 17:25:22 +0100 Subject: [PATCH 4/9] Added the assignment to the Session Card --- src/components/Medium/SessionCard.tsx | 118 ++++++++++++++------------ 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/src/components/Medium/SessionCard.tsx b/src/components/Medium/SessionCard.tsx index 71e9af97..6fdfb55c 100644 --- a/src/components/Medium/SessionCard.tsx +++ b/src/components/Medium/SessionCard.tsx @@ -40,61 +40,71 @@ export default function SessionCard({ }; return ( -
- - ID: - {session.sessionId} - - - Date: - {moment(session.date).format("DD/MM/YYYY - HH:mm")} - -
-
- {session.selectedModules.sort(sortByModuleName).map((module) => ( -
- {module === "reading" && } - {module === "listening" && } - {module === "writing" && } - {module === "speaking" && } - {module === "level" && } -
- ))} -
+
+
+ + ID: + {session.sessionId} + + + Date: + {moment(session.date).format("DD/MM/YYYY - HH:mm")} + + {session.assignment && ( + + Assignment: + {session.assignment.name} + + )}
-
- - +
+
+
+ {session.selectedModules.sort(sortByModuleName).map((module) => ( +
+ {module === "reading" && } + {module === "listening" && } + {module === "writing" && } + {module === "speaking" && } + {module === "level" && } +
+ ))} +
+
+
+ + +
); From c7ff11d0fc5b31136a2543b0b23101c2e2a2a89f Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 17:33:15 +0100 Subject: [PATCH 5/9] ENCOA-172: Updated it so if an assignment has already been started, they can't start it again --- src/dashboards/Student.tsx | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/dashboards/Student.tsx b/src/dashboards/Student.tsx index 3789748c..7b73de5f 100644 --- a/src/dashboards/Student.tsx +++ b/src/dashboards/Student.tsx @@ -29,6 +29,7 @@ import {BsArrowRepeat, BsBook, BsClipboard, BsFileEarmarkText, BsHeadphones, BsM import {toast} from "react-toastify"; import {activeAssignmentFilter} from "@/utils/assignments"; import ModuleBadge from "@/components/ModuleBadge"; +import useSessions from "@/hooks/useSessions"; interface Props { user: User; @@ -38,6 +39,7 @@ interface Props { export default function StudentDashboard({user, users, linkedCorporate}: Props) { const {gradingSystem} = useGradingSystem(); + const {sessions} = useSessions(user.id); const {data: stats} = useFilterRecordsByUser(user.id, !user?.id); const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({assignees: user?.id}); const {invites, isLoading: isInvitesLoading, reload: reloadInvites} = useInvites({to: user.id}); @@ -160,12 +162,20 @@ export default function StudentDashboard({user, users, linkedCorporate}: Props) Start
- +
x.assignment?.id === assignment.id).length > 0 && "tooltip", + )}> + +
)} {assignment.results.map((r) => r.user).includes(user.id) && ( From 2fb73cc3a39aa55bf946a572590b86935a38fc6b Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 18:54:36 +0100 Subject: [PATCH 6/9] ENCOA-166: Increased the probability of this being fixed even more --- src/pages/api/groups/index.ts | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/src/pages/api/groups/index.ts b/src/pages/api/groups/index.ts index 3493c22e..d93dd686 100644 --- a/src/pages/api/groups/index.ts +++ b/src/pages/api/groups/index.ts @@ -30,30 +30,10 @@ async function get(req: NextApiRequest, res: NextApiResponse) { participant: string; }; - if (req.session?.user?.type === "mastercorporate") { - try { - const masterCorporateGroups = await getGroupsForUser(admin, participant); - const participants = uniq(masterCorporateGroups.flatMap((g) => g.participants)); - const corporatesFromMaster = (await Promise.all(participants.map(getUser))).filter((x) => x.type === "corporate"); - - if (corporatesFromMaster.length === 0) return res.status(200).json(masterCorporateGroups); - - const groups = await Promise.all(corporatesFromMaster.map((c) => getGroupsForUser(c.id, participant))); - return res.status(200).json([...masterCorporateGroups, ...uniqBy(groups.flat(), "id")]); - } catch (e) { - console.error(e); - res.status(500).json({ok: false}); - return; - } - } - - try { - const groups = await getGroupsForUser(admin, participant); - res.status(200).json(groups); - } catch (e) { - console.error(e); - res.status(500).json({ok: false}); - } + const adminGroups = await getGroupsForUser(admin, participant); + const participants = uniq(adminGroups.flatMap((g) => g.participants)); + const groups = await Promise.all(participants.map(async (c) => await getGroupsForUser(c, participant))); + return res.status(200).json([...adminGroups, ...uniqBy(groups.flat(), "id")]); } async function post(req: NextApiRequest, res: NextApiResponse) { From 311824e8b7e81791a3e15f958e2f6792a9aadbc4 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 19:24:28 +0100 Subject: [PATCH 7/9] ENCOA-175: When a Corporate Create another Corporate, the created corporate should have access to the same students and teachers as the creator --- src/pages/api/make_user.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/pages/api/make_user.ts b/src/pages/api/make_user.ts index 062a543d..a1956f74 100644 --- a/src/pages/api/make_user.ts +++ b/src/pages/api/make_user.ts @@ -4,10 +4,12 @@ import {getFirestore, setDoc, doc, query, collection, where, getDocs, getDoc, de import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {v4} from "uuid"; -import {CorporateUser, Group} from "@/interfaces/user"; +import {CorporateUser, Group, Type} from "@/interfaces/user"; import {createUserWithEmailAndPassword, getAuth} from "firebase/auth"; import ShortUniqueId from "short-unique-id"; -import {getUserCorporate} from "@/utils/groups.be"; +import {getUserCorporate, getUserGroups} from "@/utils/groups.be"; +import {uniq} from "lodash"; +import {getUser} from "@/utils/users.be"; const DEFAULT_DESIRED_LEVELS = { reading: 9, @@ -28,6 +30,13 @@ const db = getFirestore(app); export default withIronSessionApiRoute(handler, sessionOptions); +const getUsersOfType = async (admin: string, type: Type) => { + const groups = await getUserGroups(admin); + const users = await Promise.all(uniq(groups.flatMap((x) => x.participants)).map(getUser)); + + return users.filter((x) => x.type === type).map((x) => x.id); +}; + async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") return post(req, res); @@ -106,11 +115,14 @@ async function post(req: NextApiRequest, res: NextApiResponse) { }); if (type === "corporate") { + const students = maker.type === "corporate" ? await getUsersOfType(maker.id, "student") : []; + const teachers = maker.type === "corporate" ? await getUsersOfType(maker.id, "teacher") : []; + const defaultTeachersGroup: Group = { admin: userId, id: v4(), name: "Teachers", - participants: [], + participants: teachers, disableEditing: true, }; @@ -118,21 +130,12 @@ async function post(req: NextApiRequest, res: NextApiResponse) { admin: userId, id: v4(), name: "Students", - participants: [], - disableEditing: true, - }; - - const defaultCorporateGroup: Group = { - admin: userId, - id: v4(), - name: "Corporate", - participants: [], + participants: students, disableEditing: true, }; await setDoc(doc(db, "groups", defaultTeachersGroup.id), defaultTeachersGroup); await setDoc(doc(db, "groups", defaultStudentsGroup.id), defaultStudentsGroup); - await setDoc(doc(db, "groups", defaultCorporateGroup.id), defaultCorporateGroup); } if (!!corporate) { From 680f4cfa95d8ef222e516df4f68fd1f6f979edd9 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 5 Sep 2024 19:55:19 +0100 Subject: [PATCH 8/9] Made it so it will show always the corporate --- src/utils/groups.be.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/groups.be.ts b/src/utils/groups.be.ts index b36b8921..0a911581 100644 --- a/src/utils/groups.be.ts +++ b/src/utils/groups.be.ts @@ -40,7 +40,7 @@ export const getUserCorporate = async (id: string) => { const groups = await getParticipantGroups(id); const admins = await Promise.all(groups.map((x) => x.admin).map(getUser)); - const corporates = admins.filter((x) => x.type === "corporate" || x.type === "mastercorporate"); + const corporates = admins.filter((x) => (user.type === "corporate" ? x.type === "mastercorporate" : x.type === "corporate")); if (corporates.length === 0) return undefined; return corporates.shift() as CorporateUser | MasterCorporateUser; From 55cc9765e21a0fa4480e61bb7f6a00dbf322b398 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Fri, 6 Sep 2024 09:33:30 +0100 Subject: [PATCH 9/9] Updated the backend so the users list only returns the correct ones --- src/dashboards/Corporate.tsx | 94 +++++++------------- src/dashboards/MasterCorporate.tsx | 127 ++++++++++++--------------- src/dashboards/Teacher.tsx | 91 ++++++++++++------- src/pages/(admin)/Lists/UserList.tsx | 10 +-- src/pages/api/users/list.ts | 20 +++-- 5 files changed, 163 insertions(+), 179 deletions(-) diff --git a/src/dashboards/Corporate.tsx b/src/dashboards/Corporate.tsx index 3de8527b..23a7c45a 100644 --- a/src/dashboards/Corporate.tsx +++ b/src/dashboards/Corporate.tsx @@ -207,64 +207,6 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
); - const StudentsList = () => { - const filter = (x: User) => - x.type === "student" && - (!!selectedUser - ? groups - .filter((g) => g.admin === selectedUser.id) - .flatMap((g) => g.participants) - .includes(x.id) || false - : groups.flatMap((g) => g.participants).includes(x.id)); - - return ( - ( -
-
router.push("/")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Students ({total})

-
- )} - /> - ); - }; - - const TeachersList = () => { - const filter = (x: User) => - x.type === "teacher" && - (!!selectedUser - ? groups - .filter((g) => g.admin === selectedUser.id) - .flatMap((g) => g.participants) - .includes(x.id) || false - : groups.flatMap((g) => g.participants).includes(x.id)); - - return ( - ( -
-
router.push("/")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Teachers ({total})

-
- )} - /> - ); - }; - const GroupsList = () => { const filter = (x: Group) => x.admin === user.id || x.participants.includes(user.id); @@ -518,8 +460,40 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) { )} - {router.asPath === "/#students" && } - {router.asPath === "/#teachers" && } + {router.asPath === "/#students" && ( + x.type === "student"]} + renderHeader={(total) => ( +
+
router.push("/")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> + + Back +
+

Students ({total})

+
+ )} + /> + )} + {router.asPath === "/#teachers" && ( + x.type === "teacher"]} + renderHeader={(total) => ( +
+
router.push("/")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> + + Back +
+

Teachers ({total})

+
+ )} + /> + )} {router.asPath === "/#groups" && } {router.asPath === "/#assignments" && ( user.type === "student" && corporateUserGroups.includes(user.id); - const teacherFilter = (user: User) => user.type === "teacher" && corporateUserGroups.includes(user.id); + const studentFilter = (user: User) => user.type === "student"; + const teacherFilter = (user: User) => user.type === "teacher"; const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.id); const UserDisplay = (displayUser: User) => ( @@ -365,74 +365,7 @@ export default function MasterCorporateDashboard({user}: Props) {
); - const StudentsList = () => { - const filter = (x: User) => - x.type === "student" && (!!selectedUser ? corporateUserGroups.includes(x.id) || false : corporateUserGroups.includes(x.id)); - - return ( - ( -
-
router.push("/")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Students ({total})

-
- )} - /> - ); - }; - - const TeachersList = () => { - const filter = (x: User) => - x.type === "teacher" && (!!selectedUser ? corporateUserGroups.includes(x.id) || false : corporateUserGroups.includes(x.id)); - - return ( - ( -
-
router.push("/")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Teachers ({total})

-
- )} - /> - ); - }; - - const corporateUserFilter = (x: User) => - x.type === "corporate" && (!!selectedUser ? masterCorporateUserGroups.includes(x.id) || false : masterCorporateUserGroups.includes(x.id)); - - const CorporateList = () => { - return ( - ( -
-
router.push("/")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Corporates ({total})

-
- )} - /> - ); - }; + const corporateUserFilter = (x: User) => x.type === "corporate"; const GroupsList = () => { return ( @@ -704,10 +637,58 @@ export default function MasterCorporateDashboard({user}: Props) { )} - {router.asPath === "/#students" && } - {router.asPath === "/#teachers" && } + {router.asPath === "/#students" && ( + x.type === "student"]} + renderHeader={(total) => ( +
+
router.push("/")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> + + Back +
+

Students ({total})

+
+ )} + /> + )} + {router.asPath === "/#teachers" && ( + x.type === "teacher"]} + renderHeader={(total) => ( +
+
router.push("/")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> + + Back +
+

Teachers ({total})

+
+ )} + /> + )} {router.asPath === "/#groups" && } - {router.asPath === "/#corporate" && } + {router.asPath === "/#corporate" && ( + x.type === "corporate"]} + renderHeader={(total) => ( +
+
router.push("/")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> + + Back +
+

Corporate ({total})

+
+ )} + /> + )} {router.asPath === "/#assignments" && ( state.appendUserFilter); const router = useRouter(); const assignmentsGroups = useMemo(() => groups.filter((x) => x.admin === user.id || x.participants.includes(user.id)), [groups, user.id]); @@ -90,7 +92,7 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) { setShowModal(!!selectedUser && router.asPath === "/#"); }, [selectedUser, router.asPath]); - const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id); + const studentFilter = (user: User) => user.type === "student"; const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.id); @@ -106,35 +108,6 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
); - const StudentsList = () => { - const filter = (x: User) => - x.type === "student" && - (!!selectedUser - ? groups - .filter((g) => g.admin === selectedUser.id) - .flatMap((g) => g.participants) - .includes(x.id) || false - : groups.flatMap((g) => g.participants).includes(x.id)); - - return ( - ( -
-
router.push("/")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Students ({total})

-
- )} - /> - ); - }; - const GroupsList = () => { const filter = (x: Group) => x.admin === user.id; @@ -285,16 +258,68 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) { if (shouldReload) reload(); }} onViewStudents={ - selectedUser.type === "corporate" || selectedUser.type === "teacher" ? () => router.push("/#students") : undefined + selectedUser.type === "corporate" || selectedUser.type === "teacher" + ? () => { + appendUserFilters({ + id: "view-students", + filter: (x: User) => x.type === "student", + }); + appendUserFilters({ + id: "belongs-to-admin", + filter: (x: User) => + groups + .filter((g) => g.admin === selectedUser.id || g.participants.includes(selectedUser.id)) + .flatMap((g) => g.participants) + .includes(x.id), + }); + + router.push("/list/users"); + } + : undefined + } + onViewTeachers={ + selectedUser.type === "corporate" || selectedUser.type === "student" + ? () => { + appendUserFilters({ + id: "view-teachers", + filter: (x: User) => x.type === "teacher", + }); + appendUserFilters({ + id: "belongs-to-admin", + filter: (x: User) => + groups + .filter((g) => g.admin === selectedUser.id || g.participants.includes(selectedUser.id)) + .flatMap((g) => g.participants) + .includes(x.id), + }); + + router.push("/list/users"); + } + : undefined } - onViewTeachers={selectedUser.type === "corporate" ? () => router.push("/#teachers") : undefined} user={selectedUser} />
)} - {router.asPath === "/#students" && } + {router.asPath === "/#students" && ( + x.type === "student"]} + renderHeader={(total) => ( +
+
router.push("/")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> + + Back +
+

Students ({total})

+
+ )} + /> + )} {router.asPath === "/#groups" && } {router.asPath === "/#assignments" && ( { (async () => { - if (user && users) { - const filterUsers = ["corporate", "teacher", "mastercorporate"].includes(user.type) - ? users.filter((u) => groups.flatMap((g) => g.participants).includes(u.id)) - : users; - - const filteredUsers = filters.reduce((d, f) => d.filter(f), filterUsers); + if (users) { + const filteredUsers = filters.reduce((d, f) => d.filter(f), users); const sortedUsers = await asyncSorter(filteredUsers, sortFunction); setDisplayUsers([...sortedUsers]); } })(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [user, users, sorter, groups]); + }, [users, sorter]); const deleteAccount = (user: User) => { if (!confirm(`Are you sure you want to delete ${user.name}'s account?`)) return; diff --git a/src/pages/api/users/list.ts b/src/pages/api/users/list.ts index ac569e8d..d5e8c93d 100644 --- a/src/pages/api/users/list.ts +++ b/src/pages/api/users/list.ts @@ -4,6 +4,8 @@ import {app} from "@/firebase"; import {getFirestore, collection, getDocs} from "firebase/firestore"; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; +import {getGroupsForUser} from "@/utils/groups.be"; +import {uniq} from "lodash"; const db = getFirestore(app); @@ -16,11 +18,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { } const snapshot = await getDocs(collection(db, "users")); + const users = snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })); - res.status(200).json( - snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })), - ); + if (!req.session.user) return res.status(200).json(users); + if (req.session.user.type === "admin" || req.session.user.type === "developer") return res.status(200).json(users); + + const adminGroups = await getGroupsForUser(req.session.user.id); + const groups = await Promise.all(adminGroups.flatMap((x) => x.participants).map(async (x) => await getGroupsForUser(x))); + const participants = uniq([...adminGroups.flatMap((x) => x.participants), ...groups.flat().flatMap((x) => x.participants)]); + + res.status(200).json(users.filter((x) => participants.includes(x.id))); }