Updated the code to set the participant's expiration date to use the corporate's one if it is better
This commit is contained in:
@@ -39,6 +39,8 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
const [participants, setParticipants] = useState<string[]>(
|
||||
group?.participants || [],
|
||||
);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const { openFilePicker, filesContent, clear } = useFilePicker({
|
||||
accept: ".xlsx",
|
||||
multiple: false,
|
||||
@@ -47,6 +49,8 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (filesContent.length > 0) {
|
||||
setIsLoading(true);
|
||||
|
||||
const file = filesContent[0];
|
||||
readXlsxFile(file.content).then((rows) => {
|
||||
const emails = uniq(
|
||||
@@ -64,6 +68,7 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
if (emails.length === 0) {
|
||||
toast.error("Please upload an Excel file containing e-mails!");
|
||||
clear();
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,16 +91,20 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
: "Added all students found in the file you've provided!",
|
||||
{ toastId: "upload-success" },
|
||||
);
|
||||
setIsLoading(false);
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [filesContent, user.type, users]);
|
||||
|
||||
const submit = () => {
|
||||
setIsLoading(true);
|
||||
|
||||
if (name !== group?.name && (name === "Students" || name === "Teachers")) {
|
||||
toast.error(
|
||||
"That group name is reserved and cannot be used, please enter another one.",
|
||||
);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,7 +122,10 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
toast.error("Something went wrong, please try again later!");
|
||||
return false;
|
||||
})
|
||||
.finally(onClose);
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
onClose();
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -178,6 +190,7 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
<Button
|
||||
className="w-full max-w-[300px]"
|
||||
onClick={openFilePicker}
|
||||
isLoading={isLoading}
|
||||
variant="outline"
|
||||
>
|
||||
{filesContent.length === 0
|
||||
@@ -193,6 +206,7 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
variant="outline"
|
||||
color="red"
|
||||
className="w-full max-w-[200px]"
|
||||
isLoading={isLoading}
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
@@ -200,6 +214,7 @@ const CreatePanel = ({ user, users, group, onClose }: CreateDialogProps) => {
|
||||
<Button
|
||||
className="w-full max-w-[200px]"
|
||||
onClick={submit}
|
||||
isLoading={isLoading}
|
||||
disabled={!name}
|
||||
>
|
||||
Submit
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
// 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, deleteDoc, setDoc} from "firebase/firestore";
|
||||
import {
|
||||
getFirestore,
|
||||
collection,
|
||||
getDocs,
|
||||
getDoc,
|
||||
doc,
|
||||
deleteDoc,
|
||||
setDoc,
|
||||
} from "firebase/firestore";
|
||||
import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { Group } from "@/interfaces/user";
|
||||
import { updateExpiryDateOnGroup } from "@/utils/groups.be";
|
||||
|
||||
const db = getFirestore(app);
|
||||
|
||||
@@ -47,7 +56,11 @@ async function del(req: NextApiRequest, res: NextApiResponse) {
|
||||
const group = { ...snapshot.data(), id: snapshot.id } as Group;
|
||||
|
||||
const user = req.session.user;
|
||||
if (user.type === "admin" || user.type === "developer" || user.id === group.admin) {
|
||||
if (
|
||||
user.type === "admin" ||
|
||||
user.type === "developer" ||
|
||||
user.id === group.admin
|
||||
) {
|
||||
await deleteDoc(snapshot.ref);
|
||||
|
||||
res.status(200).json({ ok: true });
|
||||
@@ -69,7 +82,22 @@ async function patch(req: NextApiRequest, res: NextApiResponse) {
|
||||
const group = { ...snapshot.data(), id: snapshot.id } as Group;
|
||||
|
||||
const user = req.session.user;
|
||||
if (user.type === "admin" || user.type === "developer" || user.id === group.admin) {
|
||||
if (
|
||||
user.type === "admin" ||
|
||||
user.type === "developer" ||
|
||||
user.id === group.admin
|
||||
) {
|
||||
if ("participants" in req.body) {
|
||||
const newParticipants = (req.body.participants as string[]).filter(
|
||||
(x) => !group.participants.includes(x),
|
||||
);
|
||||
await Promise.all(
|
||||
newParticipants.map(
|
||||
async (p) => await updateExpiryDateOnGroup(p, group.admin),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await setDoc(snapshot.ref, req.body, { merge: true });
|
||||
|
||||
res.status(200).json({ ok: true });
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
// 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, setDoc, doc, query, where} from "firebase/firestore";
|
||||
import {
|
||||
getFirestore,
|
||||
collection,
|
||||
getDocs,
|
||||
setDoc,
|
||||
doc,
|
||||
query,
|
||||
where,
|
||||
} from "firebase/firestore";
|
||||
import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { Group } from "@/interfaces/user";
|
||||
import { v4 } from "uuid";
|
||||
import { updateExpiryDateOnGroup } from "@/utils/groups.be";
|
||||
|
||||
const db = getFirestore(app);
|
||||
|
||||
@@ -22,13 +31,22 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
const {admin, participant} = req.query as {admin: string; participant: string};
|
||||
const { admin, participant } = req.query as {
|
||||
admin: string;
|
||||
participant: string;
|
||||
};
|
||||
|
||||
const queryConstraints = [
|
||||
...(admin ? [where("admin", "==", admin)] : []),
|
||||
...(participant ? [where("participants", "array-contains", participant)] : []),
|
||||
...(participant
|
||||
? [where("participants", "array-contains", participant)]
|
||||
: []),
|
||||
];
|
||||
const snapshot = await getDocs(queryConstraints.length > 0 ? query(collection(db, "groups"), ...queryConstraints) : collection(db, "groups"));
|
||||
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(),
|
||||
@@ -40,6 +58,16 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
const body = req.body as Group;
|
||||
|
||||
await setDoc(doc(db, "groups", v4()), {name: body.name, admin: body.admin, participants: body.participants});
|
||||
await Promise.all(
|
||||
body.participants.map(
|
||||
async (p) => await updateExpiryDateOnGroup(p, body.admin),
|
||||
),
|
||||
);
|
||||
|
||||
await setDoc(doc(db, "groups", v4()), {
|
||||
name: body.name,
|
||||
admin: body.admin,
|
||||
participants: body.participants,
|
||||
});
|
||||
res.status(200).json({ ok: true });
|
||||
}
|
||||
|
||||
53
src/utils/groups.be.ts
Normal file
53
src/utils/groups.be.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { app } from "@/firebase";
|
||||
import { CorporateUser, StudentUser, TeacherUser } from "@/interfaces/user";
|
||||
import { doc, getDoc, getFirestore, setDoc } from "firebase/firestore";
|
||||
import moment from "moment";
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
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 },
|
||||
);
|
||||
}
|
||||
|
||||
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 },
|
||||
);
|
||||
|
||||
return;
|
||||
};
|
||||
@@ -2,17 +2,23 @@ import {CorporateUser, Group, User} from "@/interfaces/user";
|
||||
import axios from "axios";
|
||||
|
||||
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}`))
|
||||
.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(
|
||||
(g) => users.find((u) => u.id === g.admin)?.type,
|
||||
);
|
||||
return adminTypes.includes("corporate");
|
||||
};
|
||||
|
||||
export const getUserCorporate = async (userID: string) => {
|
||||
const groups = (await axios.get<Group[]>(`/api/groups?participant=${userID}`)).data;
|
||||
const groups = (await axios.get<Group[]>(`/api/groups?participant=${userID}`))
|
||||
.data;
|
||||
const users = (await axios.get<User[]>("/api/users/list")).data;
|
||||
|
||||
const admins = groups.map((g) => users.find((u) => u.id === g.admin)).filter((x) => x?.type === "corporate");
|
||||
const admins = groups
|
||||
.map((g) => users.find((u) => u.id === g.admin))
|
||||
.filter((x) => x?.type === "corporate");
|
||||
return admins.length > 0 ? (admins[0] as CorporateUser) : undefined;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user