diff --git a/public/orange-stock-photo.jpg b/public/orange-stock-photo.jpg new file mode 100644 index 00000000..821d0f82 Binary files /dev/null and b/public/orange-stock-photo.jpg differ diff --git a/public/red-stock-photo.jpg b/public/red-stock-photo.jpg new file mode 100644 index 00000000..3d5ab68b Binary files /dev/null and b/public/red-stock-photo.jpg differ diff --git a/src/components/UserCard.tsx b/src/components/UserCard.tsx index ba02b079..3efd3ac2 100644 --- a/src/components/UserCard.tsx +++ b/src/components/UserCard.tsx @@ -78,7 +78,7 @@ const UserCard = ({user, loggedInUser, onClose, onViewStudents, onViewTeachers, const [status, setStatus] = useState(user.status); const [referralAgentLabel, setReferralAgentLabel] = useState(); const [position, setPosition] = useState(user.type === "corporate" ? user.demographicInformation?.position : undefined); - const [passport_id, setPassportID] = useState(user.type === "student" ? user.demographicInformation?.passport_id : undefined); + const [studentID, setStudentID] = useState(user.type === "student" ? user.studentID : undefined); const [referralAgent, setReferralAgent] = useState(user.type === "corporate" ? user.corporateInformation?.referralAgent : undefined); const [companyName, setCompanyName] = useState( @@ -123,6 +123,7 @@ const UserCard = ({user, loggedInUser, onClose, onViewStudents, onViewTeachers, .post<{user?: User; ok?: boolean}>(`/api/users/update?id=${user.id}`, { ...user, subscriptionExpirationDate: expiryDate, + studentID, type, status, agentInformation: @@ -248,7 +249,7 @@ const UserCard = ({user, loggedInUser, onClose, onViewStudents, onViewTeachers, onChange={setCompanyName} placeholder="Enter corporate name" defaultValue={companyName} - disabled={disabled} + disabled={disabled || checkAccess(loggedInUser, getTypesOfUser(["developer", "admin"]))} /> setUserAmount(e ? parseInt(e) : undefined)} placeholder="Enter number of users" defaultValue={userAmount} - disabled={disabled} + disabled={disabled || checkAccess(loggedInUser, getTypesOfUser(["developer", "admin"]))} /> setMonthlyDuration(e ? parseInt(e) : undefined)} placeholder="Enter monthly duration" defaultValue={monthlyDuration} - disabled={disabled} + disabled={disabled || checkAccess(loggedInUser, getTypesOfUser(["developer", "admin"]))} />
@@ -277,7 +278,7 @@ const UserCard = ({user, loggedInUser, onClose, onViewStudents, onViewTeachers, type="number" defaultValue={paymentValue || 0} className="col-span-3" - disabled={disabled} + disabled={disabled || checkAccess(loggedInUser, getTypesOfUser(["developer", "admin"]))} /> null} - placeholder="Enter National ID or Passport number" - value={user.type === "student" ? user.demographicInformation?.passport_id : undefined} - disabled - required - /> +
+ null} + placeholder="Enter National ID or Passport number" + value={user.type === "student" ? user.demographicInformation?.passport_id : undefined} + disabled + required + /> + +
)}
diff --git a/src/constants/userPermissions.ts b/src/constants/userPermissions.ts index af3e7543..8716c301 100644 --- a/src/constants/userPermissions.ts +++ b/src/constants/userPermissions.ts @@ -1,91 +1,91 @@ -import { Type } from "@/interfaces/user"; +import {Type} from "@/interfaces/user"; export const PERMISSIONS = { - generateCode: { - student: ["corporate", "developer", "admin", "mastercorporate"], - teacher: ["corporate", "developer", "admin", "mastercorporate"], - corporate: ["admin", "developer"], - mastercorporate: ["admin", "developer"], + generateCode: { + student: ["corporate", "developer", "admin", "mastercorporate"], + teacher: ["corporate", "developer", "admin", "mastercorporate"], + corporate: ["admin", "developer"], + mastercorporate: ["admin", "developer"], - admin: ["developer", "admin"], - agent: ["developer", "admin"], - developer: ["developer"], - }, - deleteUser: { - student: { - perm: "deleteStudent", - list: ["corporate", "developer", "admin", "mastercorporate"], - }, - teacher: { - perm: "deleteTeacher", - list: ["corporate", "developer", "admin", "mastercorporate"], - }, - corporate: { - perm: "deleteCorporate", - list: ["admin", "developer"], - }, - mastercorporate: { - perm: undefined, - list: ["admin", "developer"], - }, + admin: ["developer", "admin"], + agent: ["developer", "admin"], + developer: ["developer"], + }, + deleteUser: { + student: { + perm: "deleteStudent", + list: ["corporate", "developer", "admin", "mastercorporate"], + }, + teacher: { + perm: "deleteTeacher", + list: ["corporate", "developer", "admin", "mastercorporate"], + }, + corporate: { + perm: "deleteCorporate", + list: ["admin", "developer"], + }, + mastercorporate: { + perm: undefined, + list: ["admin", "developer"], + }, - admin: { - perm: "deleteAdmin", - list: ["developer", "admin"], - }, - agent: { - perm: "deleteCountryManager", - list: ["developer", "admin"], - }, - developer: { - perm: undefined, - list: ["developer"], - }, - }, - updateUser: { - student: { - perm: "editStudent", - list: ["developer", "admin"], - }, - teacher: { - perm: "editTeacher", - list: ["developer", "admin"], - }, + admin: { + perm: "deleteAdmin", + list: ["developer", "admin"], + }, + agent: { + perm: "deleteCountryManager", + list: ["developer", "admin"], + }, + developer: { + perm: undefined, + list: ["developer"], + }, + }, + updateUser: { + student: { + perm: "editStudent", + list: ["developer", "admin", "corporate", "mastercorporate", "teacher"], + }, + teacher: { + perm: "editTeacher", + list: ["developer", "admin", "corporate", "mastercorporate"], + }, - corporate: { - perm: "editCorporate", - list: ["admin", "developer"], - }, - mastercorporate: { - perm: undefined, - list: ["admin", "developer"], - }, + corporate: { + perm: "editCorporate", + list: ["developer", "admin", "mastercorporate"], + }, + mastercorporate: { + perm: undefined, + list: ["admin", "developer"], + }, - admin: { - perm: "editAdmin", - list: ["developer", "admin"], - }, + admin: { + perm: "editAdmin", + list: ["developer", "admin"], + }, - agent: { - perm: "editCountryManager", - list: ["developer", "admin"], - }, - developer: { - perm: undefined, - list: ["developer"], - }, - }, - updateExpiryDate: { - student: ["developer", "admin"], - teacher: ["developer", "admin"], - corporate: ["admin", "developer"], - mastercorporate: ["admin", "developer"], + agent: { + perm: "editCountryManager", + list: ["developer", "admin"], + }, + developer: { + perm: undefined, + list: ["developer"], + }, + }, + updateExpiryDate: { + student: ["developer", "admin"], + teacher: ["developer", "admin"], + corporate: ["admin", "developer"], + mastercorporate: ["admin", "developer"], - admin: ["developer", "admin"], - agent: ["developer", "admin"], - developer: ["developer"], - }, - examManagement: { - delete: ["developer", "admin"], - }, + admin: ["developer", "admin"], + agent: ["developer", "admin"], + developer: ["developer"], + }, + examManagement: { + delete: ["developer", "admin"], + }, }; diff --git a/src/exams/pdf/level.test.report.tsx b/src/exams/pdf/level.test.report.tsx new file mode 100644 index 00000000..c09cba73 --- /dev/null +++ b/src/exams/pdf/level.test.report.tsx @@ -0,0 +1,235 @@ +/* eslint-disable jsx-a11y/alt-text */ +import React from "react"; +import { Document, Page, View, Text, Image } from "@react-pdf/renderer"; +import { ModuleScore } from "@/interfaces/module.scores"; +import { styles } from "./styles"; +import TestReportFooter from "./test.report.footer"; + +import { StyleSheet } from "@react-pdf/renderer"; + +const customStyles = StyleSheet.create({ + testDetails: { + display: "flex", + gap: 4, + }, + testDetailsContainer: { + display: "flex", + gap: 16, + }, + table: { + width: "100%", + }, + tableRow: { + flexDirection: "row", + }, + tableCol70: { + width: "70%", // First column width (50%) + borderStyle: "solid", + borderWidth: 1, + borderColor: "#000", + // padding: 5, + }, + tableCol25: { + width: "16.67%", // Remaining four columns each get 1/6 of the total width (50% / 3 = 16.67%) + borderStyle: "solid", + borderWidth: 1, + borderColor: "#000", + padding: 5, + }, + tableCol20: { + width: "20%", // Width for each of the 5 sub-columns (50% / 5 = 20%) + borderStyle: "solid", + borderWidth: 1, + borderColor: "#000", + padding: 5, + }, + tableCol10: { + width: "10%", // Width for each of the 5 sub-columns (50% / 5 = 20%) + borderStyle: "solid", + borderWidth: 1, + borderColor: "#000", + padding: 5, + }, + tableCellHeader: { + fontSize: 12, + textAlign: "center", + }, + tableCellHeaderColor: { + backgroundColor: "#d3d3d3", + }, + tableCell: { + fontSize: 10, + textAlign: "center", + }, +}); + +interface Props { + date: string; + name: string; + email: string; + id: string; + gender?: string; + passportId: string; + corporateName: string; + downloadDate: string; + userId: string; + uniqueExercises: { name: string; result: string }[]; + timeSpent: string; + score: string; +} + +const LevelTestReport = ({ + date, + name, + email, + id, + gender, + passportId, + corporateName, + downloadDate, + userId, + uniqueExercises, + timeSpent, + score, +}: Props) => { + const defaultTextStyle = [styles.textFont, { fontSize: 8 }]; + return ( + + + + Corporate Name: {corporateName} + + + + Report Download date: {downloadDate} + + + + Test Information: {id} + + + Date of Test: {date} + Candidates name: {name} + Email: {email} + National ID: {passportId} + + Gender: {gender} + Candidate ID: {userId} + + + + {/* Header Row */} + + + + Test sections + + + + Time spent + + + Score + + + + + + {uniqueExercises.map((exercise, index) => ( + + Part {index + 1} + + ))} + + + + + + + + + + + + + + {uniqueExercises.map((exercise, index) => ( + + {exercise.name} + + ))} + + + + + + + + + + + + + {uniqueExercises.map((exercise, index) => ( + + + {exercise.result} + + + ))} + + + + {timeSpent} + + + {score} + + + + + + + ); +}; + +export default LevelTestReport; diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts index d248eea8..d4699270 100644 --- a/src/interfaces/user.ts +++ b/src/interfaces/user.ts @@ -26,6 +26,7 @@ export interface BasicUser { export interface StudentUser extends BasicUser { type: "student"; + studentID?: string; preferredGender?: InstructorGender; demographicInformation?: DemographicInformation; preferredTopics?: string[]; @@ -135,7 +136,11 @@ export interface Stat { missing: number; }; isDisabled?: boolean; - shuffleMaps?: ShuffleMap[]; + shuffleMaps?: ShuffleMap[]; + pdf?: { + path: string; + version: string; + }; } export interface Group { diff --git a/src/pages/(admin)/BatchCodeGenerator.tsx b/src/pages/(admin)/BatchCodeGenerator.tsx index e17f5281..313264eb 100644 --- a/src/pages/(admin)/BatchCodeGenerator.tsx +++ b/src/pages/(admin)/BatchCodeGenerator.tsx @@ -19,6 +19,7 @@ import {BsFileEarmarkEaselFill, BsQuestionCircleFill} from "react-icons/bs"; import {checkAccess, getTypesOfUser} from "@/utils/permissions"; import {PermissionType} from "@/interfaces/permissions"; import usePermissions from "@/hooks/usePermissions"; + const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/); const USER_TYPE_PERMISSIONS: { @@ -34,7 +35,7 @@ const USER_TYPE_PERMISSIONS: { }, agent: { perm: "createCodeCountryManager", - list: [], + list: ["student", "teacher", "corporate", "mastercorporate"], }, corporate: { perm: "createCodeCorporate", @@ -85,7 +86,7 @@ export default function BatchCodeGenerator({user}: {user: User}) { const information = uniqBy( rows .map((row) => { - const [firstName, lastName, country, passport_id, email, ...phone] = row as string[]; + const [firstName, lastName, country, passport_id, email, phone] = row as string[]; return EMAIL_REGEX.test(email.toString().trim()) ? { email: email.toString().trim().toLowerCase(), diff --git a/src/pages/(admin)/BatchCreateUser.tsx b/src/pages/(admin)/BatchCreateUser.tsx index d0d50c57..409b710a 100644 --- a/src/pages/(admin)/BatchCreateUser.tsx +++ b/src/pages/(admin)/BatchCreateUser.tsx @@ -11,10 +11,13 @@ import Modal from "@/components/Modal"; import {BsQuestionCircleFill} from "react-icons/bs"; import {PermissionType} from "@/interfaces/permissions"; import moment from "moment"; -import {checkAccess} from "@/utils/permissions"; +import {checkAccess, getTypesOfUser} from "@/utils/permissions"; import Checkbox from "@/components/Low/Checkbox"; import ReactDatePicker from "react-datepicker"; import clsx from "clsx"; +import usePermissions from "@/hooks/usePermissions"; +import countryCodes from "country-codes-list"; + const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/); type Type = Exclude; @@ -26,7 +29,7 @@ const USER_TYPE_LABELS: {[key in Type]: string} = { }; const USER_TYPE_PERMISSIONS: { - [key in Type]: {perm: PermissionType | undefined; list: Type[]}; + [key in UserType]: {perm: PermissionType | undefined; list: UserType[]}; } = { student: { perm: "createCodeStudent", @@ -36,10 +39,26 @@ const USER_TYPE_PERMISSIONS: { perm: "createCodeTeacher", list: [], }, + agent: { + perm: "createCodeCountryManager", + list: ["student", "teacher", "corporate", "mastercorporate"], + }, corporate: { perm: "createCodeCorporate", list: ["student", "teacher"], }, + mastercorporate: { + perm: undefined, + list: ["student", "teacher", "corporate"], + }, + admin: { + perm: "createCodeAdmin", + list: ["student", "teacher", "agent", "corporate", "admin", "mastercorporate"], + }, + developer: { + perm: undefined, + list: ["student", "teacher", "agent", "corporate", "admin", "developer", "mastercorporate"], + }, }; export default function BatchCreateUser({user}: {user: User}) { @@ -65,6 +84,7 @@ export default function BatchCreateUser({user}: {user: User}) { const [showHelp, setShowHelp] = useState(false); const {users} = useUsers(); + const {permissions} = usePermissions(user?.id || ""); const {openFilePicker, filesContent, clear} = useFilePicker({ accept: ".xlsx", @@ -84,7 +104,11 @@ export default function BatchCreateUser({user}: {user: User}) { const information = uniqBy( rows .map((row) => { - const [firstName, lastName, country, passport_id, email, phone, group] = row as string[]; + const [firstName, lastName, country, passport_id, email, phone, group, studentID] = row as string[]; + const countryItem = + countryCodes.findOne("countryCode" as any, country.toUpperCase()) || + countryCodes.all().find((x) => x.countryNameEn.toLowerCase() === country.toLowerCase()); + return EMAIL_REGEX.test(email.toString().trim()) ? { email: email.toString().trim().toLowerCase(), @@ -92,8 +116,9 @@ export default function BatchCreateUser({user}: {user: User}) { type: type, passport_id: passport_id?.toString().trim() || undefined, groupName: group, + studentID, demographicInformation: { - country: country, + country: countryItem?.countryCode, passport_id: passport_id?.toString().trim() || undefined, phone, }, @@ -158,6 +183,7 @@ export default function BatchCreateUser({user}: {user: User}) { E-mail Phone Number Group Name + Student ID @@ -214,11 +240,17 @@ export default function BatchCreateUser({user}: {user: User}) { defaultValue="student" onChange={(e) => setType(e.target.value as Type)} className="flex min-h-[70px] w-full min-w-[350px] cursor-pointer justify-center rounded-full border bg-white p-6 text-sm font-normal focus:outline-none"> - {Object.keys(USER_TYPE_LABELS).map((type) => ( - - ))} + {Object.keys(USER_TYPE_LABELS) + .filter((x) => { + const {list, perm} = USER_TYPE_PERMISSIONS[x as Type]; + // if (x === "corporate") console.log(list, perm, checkAccess(user, list, permissions, perm)); + return checkAccess(user, getTypesOfUser(list), permissions, perm); + }) + .map((type) => ( + + ))} )} + ) as any, + cell: (info) => info.getValue() || "N/A", + }), columnHelper.accessor("corporateInformation.companyInformation.name", { header: ( - - - Don't have an account?{" "} - - Sign up - - - - )} - {user && !user.isVerified && ( - - )} - - - - ); + return ( + <> + + Login | EnCoach + + + + +
+ +
+ {/*
*/} + People smiling looking at a tablet +
+
+
+ EnCoach's Logo +

Login to your account

+

with your registered Email Address

+
+ + {!user && ( + <> +
+ setEmail(e.toLowerCase())} placeholder="Enter email address" /> + setPassword(e)} placeholder="Password" /> +
+
setRememberPassword((prev) => !prev)}> + +
+ +
+ Remember my password +
+ + Forgot Password? + +
+ +
+ + Don't have an account?{" "} + + Sign up + + + + )} + {user && !user.isVerified && } +
+
+ + ); } diff --git a/src/pages/record.tsx b/src/pages/record.tsx index 66bc971f..59481dfb 100644 --- a/src/pages/record.tsx +++ b/src/pages/record.tsx @@ -22,6 +22,7 @@ import {usePDFDownload} from "@/hooks/usePDFDownload"; import useRecordStore from "@/stores/recordStore"; import useTrainingContentStore from "@/stores/trainingContentStore"; import StatsGridItem from "@/components/StatGridItem"; +import {checkAccess} from "@/utils/permissions"; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; @@ -68,10 +69,9 @@ export default function History({user}: {user: User}) { const {assignments} = useAssignments({}); const {users} = useUsers(); - const {stats, isLoading: isStatsLoading} = useStats(user?.type === "student" ? user?.id : statsUserId); + const {stats, isLoading: isStatsLoading} = useStats(statsUserId || user?.id); const {groups: allGroups} = useGroups({}); - - const groups = allGroups.filter((x) => x.admin === user.id); + const {groups} = useGroups({admin: user?.id, userType: user?.type}); const setExams = useExamStore((state) => state.setExams); const setShowSolutions = useExamStore((state) => state.setShowSolutions); @@ -82,6 +82,8 @@ export default function History({user}: {user: User}) { const renderPdfIcon = usePDFDownload("stats"); const router = useRouter(); + useEffect(() => setStatsUserId(user.id), [setStatsUserId, user]); + useEffect(() => { if (stats && !isStatsLoading) { setGroupedStats( @@ -197,6 +199,7 @@ export default function History({user}: {user: User}) { const selectableCorporates = [ defaultSelectableCorporate, ...users + .filter((x) => groups.flatMap((g) => [g.admin, ...g.participants]).includes(x.id)) .filter((x) => x.type === "corporate") .map((x) => ({ value: x.id, @@ -208,26 +211,14 @@ export default function History({user}: {user: User}) { const getUsersList = (): User[] => { if (selectedCorporate) { - // get groups for that corporate const selectedCorporateGroups = allGroups.filter((x) => x.admin === selectedCorporate); - - // get the teacher ids for that group const selectedCorporateGroupsParticipants = selectedCorporateGroups.flatMap((x) => x.participants); - // // search for groups for these teachers - // const teacherGroups = allGroups.filter((x) => { - // return selectedCorporateGroupsParticipants.includes(x.admin); - // }); - - // const usersList = [ - // ...selectedCorporateGroupsParticipants, - // ...teacherGroups.flatMap((x) => x.participants), - // ]; const userListWithUsers = selectedCorporateGroupsParticipants.map((x) => users.find((y) => y.id === x)) as User[]; return userListWithUsers.filter((x) => x); } - return users || []; + return user.type !== "mastercorporate" ? users : users.filter((x) => groups.flatMap((g) => [g.admin, ...g.participants]).includes(x.id)); }; const corporateFilteredUserList = getUsersList(); @@ -267,7 +258,7 @@ export default function History({user}: {user: User}) {
- {(user.type === "developer" || user.type === "admin") && !training && ( + {checkAccess(user, ["developer", "admin", "mastercorporate"]) && !training && ( <> diff --git a/src/pages/register.tsx b/src/pages/register.tsx index 1da21305..3cfda76d 100644 --- a/src/pages/register.tsx +++ b/src/pages/register.tsx @@ -55,8 +55,7 @@ export default function Register({code: queryCode}: {code: string}) {
-
- People smiling looking at a tablet + People smiling looking at a tablet
diff --git a/src/pages/settings.tsx b/src/pages/settings.tsx index 80c08fbb..8fc93230 100644 --- a/src/pages/settings.tsx +++ b/src/pages/settings.tsx @@ -62,9 +62,9 @@ export default function Admin() {
- {checkAccess(user, getTypesOfUser(["teacher"]), permissions, "viewCodes") && ( <> + diff --git a/src/utils/groups.be.ts b/src/utils/groups.be.ts index bba422ff..d1a57f72 100644 --- a/src/utils/groups.be.ts +++ b/src/utils/groups.be.ts @@ -1,107 +1,173 @@ -import {app} from "@/firebase"; -import {CorporateUser, Group, StudentUser, TeacherUser} from "@/interfaces/user"; -import {collection, doc, getDoc, getDocs, getFirestore, query, setDoc, where} from "firebase/firestore"; +import { app } from "@/firebase"; +import { + CorporateUser, + Group, + StudentUser, + TeacherUser, +} from "@/interfaces/user"; +import { + collection, + doc, + getDoc, + getDocs, + getFirestore, + query, + setDoc, + where, +} from "firebase/firestore"; import moment from "moment"; -import {getUser} from "./users.be"; - +import { getUser } from "./users.be"; +import { getSpecificUsers } from "./users.be"; const db = getFirestore(app); -export const updateExpiryDateOnGroup = async (participantID: string, corporateID: string) => { - const corporateRef = await getDoc(doc(db, "users", corporateID)); - const participantRef = await getDoc(doc(db, "users", participantID)); +export const updateExpiryDateOnGroup = async ( + participantID: string, + corporateID: string +) => { + const corporateRef = await getDoc(doc(db, "users", corporateID)); + const participantRef = await getDoc(doc(db, "users", participantID)); - if (!corporateRef.exists() || !participantRef.exists()) return; + if (!corporateRef.exists() || !participantRef.exists()) return; - const corporate = { - ...corporateRef.data(), - id: corporateRef.id, - } as CorporateUser; - const participant = {...participantRef.data(), id: participantRef.id} as StudentUser | TeacherUser; + const corporate = { + ...corporateRef.data(), + id: corporateRef.id, + } as CorporateUser; + const participant = { ...participantRef.data(), id: participantRef.id } as + | StudentUser + | TeacherUser; - if (corporate.type !== "corporate" || (participant.type !== "student" && participant.type !== "teacher")) return; + if ( + corporate.type !== "corporate" || + (participant.type !== "student" && participant.type !== "teacher") + ) + return; - if (!corporate.subscriptionExpirationDate || !participant.subscriptionExpirationDate) { - return await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: null}, {merge: true}); - } + if ( + !corporate.subscriptionExpirationDate || + !participant.subscriptionExpirationDate + ) { + return await setDoc( + doc(db, "users", participant.id), + { subscriptionExpirationDate: null }, + { merge: true } + ); + } - const corporateDate = moment(corporate.subscriptionExpirationDate); - const participantDate = moment(participant.subscriptionExpirationDate); + const corporateDate = moment(corporate.subscriptionExpirationDate); + const participantDate = moment(participant.subscriptionExpirationDate); - if (corporateDate.isAfter(participantDate)) - return await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: corporateDate.toISOString()}, {merge: true}); + if (corporateDate.isAfter(participantDate)) + return await setDoc( + doc(db, "users", participant.id), + { subscriptionExpirationDate: corporateDate.toISOString() }, + { merge: true } + ); - return; + return; }; export const getGroups = async () => { - const groupDocs = await getDocs(collection(db, "groups")); - return groupDocs.docs.map((x) => ({...x.data(), id: x.id})) as Group[]; + const groupDocs = await getDocs(collection(db, "groups")); + return groupDocs.docs.map((x) => ({ ...x.data(), id: x.id })) as Group[]; }; export const getUserGroups = async (id: string): Promise => { - const groupDocs = await getDocs(query(collection(db, "groups"), where("admin", "==", id))); - return groupDocs.docs.map((x) => ({...x.data(), id})) as Group[]; + const groupDocs = await getDocs( + query(collection(db, "groups"), where("admin", "==", id)) + ); + return groupDocs.docs.map((x) => ({ ...x.data(), id })) as Group[]; }; -export const getAllAssignersByCorporate = async (corporateID: string): Promise => { - const groups = await getUserGroups(corporateID); - const groupUsers = (await Promise.all(groups.map(async (g) => await Promise.all(g.participants.map(getUser))))).flat(); - const teacherPromises = await Promise.all( - groupUsers.map(async (u) => - u.type === "teacher" ? u.id : u.type === "corporate" ? [...(await getAllAssignersByCorporate(u.id)), u.id] : undefined, - ), - ); +export const getAllAssignersByCorporate = async ( + corporateID: string +): Promise => { + const groups = await getUserGroups(corporateID); + const groupUsers = ( + await Promise.all( + groups.map(async (g) => await Promise.all(g.participants.map(getUser))) + ) + ).flat(); + const teacherPromises = await Promise.all( + groupUsers.map(async (u) => + u.type === "teacher" + ? u.id + : u.type === "corporate" + ? [...(await getAllAssignersByCorporate(u.id)), u.id] + : undefined + ) + ); - return teacherPromises.filter((x) => !!x).flat() as string[]; + return teacherPromises.filter((x) => !!x).flat() as string[]; }; export const getGroupsForUser = async (admin: string, participant: string) => { - try { - const queryConstraints = [ - ...(admin ? [where("admin", "==", admin)] : []), - ...(participant - ? [where("participants", "array-contains", participant)] - : []), - ]; - const snapshot = await getDocs( - queryConstraints.length > 0 - ? query(collection(db, "groups"), ...queryConstraints) - : collection(db, "groups") - ); - const groups = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as Group[]; - - return groups; - } catch (e) { - console.error(e); - return []; - } - }; + try { + const queryConstraints = [ + ...(admin ? [where("admin", "==", admin)] : []), + ...(participant + ? [where("participants", "array-contains", participant)] + : []), + ]; + const snapshot = await getDocs( + queryConstraints.length > 0 + ? query(collection(db, "groups"), ...queryConstraints) + : collection(db, "groups") + ); + const groups = snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as Group[]; - export const getStudentGroupsForUsersWithoutAdmin = async (admin: string, participants: string[]) => { - try { - const queryConstraints = [ - ...(admin ? [where("admin", "!=", admin)] : []), - ...(participants - ? [where("participants", "array-contains-any", participants)] - : []), - where("name", "==", "Students"), - ]; - const snapshot = await getDocs( - queryConstraints.length > 0 - ? query(collection(db, "groups"), ...queryConstraints) - : collection(db, "groups") - ); - const groups = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as Group[]; - - return groups; - } catch (e) { - console.error(e); - return []; - } - }; \ No newline at end of file + return groups; + } catch (e) { + console.error(e); + return []; + } +}; + +export const getStudentGroupsForUsersWithoutAdmin = async ( + admin: string, + participants: string[] +) => { + try { + const queryConstraints = [ + ...(admin ? [where("admin", "!=", admin)] : []), + ...(participants + ? [where("participants", "array-contains-any", participants)] + : []), + where("name", "==", "Students"), + ]; + const snapshot = await getDocs( + queryConstraints.length > 0 + ? query(collection(db, "groups"), ...queryConstraints) + : collection(db, "groups") + ); + const groups = snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as Group[]; + + return groups; + } catch (e) { + console.error(e); + return []; + } +}; + +export const getCorporateNameForStudent = async (studentID: string) => { + const groups = await getStudentGroupsForUsersWithoutAdmin("", [studentID]); + if (groups.length === 0) return ''; + + const adminUserIds = [...new Set(groups.map((g) => g.admin))]; + const adminUsersData = await getSpecificUsers(adminUserIds); + + if(adminUsersData.length === 0) return ''; + const admins = adminUsersData.filter((x) => x.type === 'corporate'); + + if(admins.length > 0) { + return (admins[0] as CorporateUser).corporateInformation.companyInformation.name; + } + + return ''; +}; diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 0831393d..da3d2d59 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -9,12 +9,10 @@ export function checkAccess(user: User, types: Type[], permissions?: PermissionT // if(user.type === '') { if (!user.type) { - console.warn("User type is empty"); return false; } if (types.length === 0) { - console.warn("No types provided"); return false; }