diff --git a/src/dashboards/Agent.tsx b/src/dashboards/Agent.tsx
index dbfb56cc..bf925114 100644
--- a/src/dashboards/Agent.tsx
+++ b/src/dashboards/Agent.tsx
@@ -2,20 +2,17 @@
import Modal from "@/components/Modal";
import useStats from "@/hooks/useStats";
import useUsers from "@/hooks/useUsers";
-import {Group, Stat, User} from "@/interfaces/user";
+import { User} from "@/interfaces/user";
import UserList from "@/pages/(admin)/Lists/UserList";
import {dateSorter} from "@/utils";
import moment from "moment";
import {useEffect, useState} from "react";
-import {BsArrowLeft, BsPersonFill, BsBank} from "react-icons/bs";
+import {BsArrowLeft, BsPersonFill, BsBank, BsCurrencyDollar} from "react-icons/bs";
import UserCard from "@/components/UserCard";
import useGroups from "@/hooks/useGroups";
-import {calculateAverageLevel, calculateBandScore} from "@/utils/score";
-import {MODULE_ARRAY} from "@/utils/moduleUtils";
-import {Module} from "@/interfaces";
-import {groupByExam} from "@/utils/stats";
+
import IconCard from "./IconCard";
-import GroupList from "@/pages/(admin)/Lists/GroupList";
+import usePaymentStatusUsers from '@/hooks/usePaymentStatusUsers';
interface Props {
user: User;
@@ -29,6 +26,7 @@ export default function AgentDashboard({user}: Props) {
const {stats} = useStats();
const {users, reload} = useUsers();
const {groups} = useGroups(user.id);
+ const { pending, done } = usePaymentStatusUsers();
useEffect(() => {
setShowModal(!!selectedUser && page === "");
@@ -106,7 +104,26 @@ export default function AgentDashboard({user}: Props) {
Corporate ({users.filter(filter).length})
+
+ >
+ );
+ };
+ const CorporatePaidStatusList = ({ paid }: {paid: Boolean}) => {
+ const list = paid ? done : pending;
+ const filter = (x: User) => x.type === "corporate" && list.includes(x.id);
+
+ return (
+ <>
+
+
setPage("")}
+ className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
+
+ Back
+
+
{paid ? 'Payment Done' : 'Pending Payment'} ({list.length})
+
>
);
@@ -136,6 +153,20 @@ export default function AgentDashboard({user}: Props) {
value={users.filter(corporateFilter).length}
color="purple"
/>
+ setPage("paymentdone")}
+ Icon={BsCurrencyDollar}
+ label="Payment Done"
+ value={done.length}
+ color="purple"
+ />
+ setPage("paymentdone")}
+ Icon={BsCurrencyDollar}
+ label="Pending Payment"
+ value={pending.length}
+ color="rose"
+ />
@@ -205,6 +236,8 @@ export default function AgentDashboard({user}: Props) {
{page === "referredCorporate" && }
{page === "corporate" && }
{page === "inactiveReferredCorporate" && }
+ {page === "paymentdone" && }
+ {page === "paymentpending" && }
{page === "" && }
>
);
diff --git a/src/hooks/usePaymentStatusUsers.tsx b/src/hooks/usePaymentStatusUsers.tsx
new file mode 100644
index 00000000..5b2bbd94
--- /dev/null
+++ b/src/hooks/usePaymentStatusUsers.tsx
@@ -0,0 +1,20 @@
+import axios from "axios";
+import { useEffect, useState } from "react";
+import { PaymentsStatus } from "@/interfaces/user.payments";
+
+export default function usePaymentStatusUsers() {
+ const [{ pending, done }, setStatus] = useState({
+ pending: [],
+ done: [],
+ });
+
+ const getData = () => {
+ axios.get("/api/payments/assigned").then((response) => {
+ setStatus(response.data);
+ });
+ };
+
+ useEffect(getData, []);
+
+ return { pending, done };
+}
diff --git a/src/interfaces/user.payments.ts b/src/interfaces/user.payments.ts
new file mode 100644
index 00000000..c555b919
--- /dev/null
+++ b/src/interfaces/user.payments.ts
@@ -0,0 +1,5 @@
+// these arrays contain the ids of the corporates that have paid or not paid
+export interface PaymentsStatus {
+ pending: string[];
+ done: string[];
+}
\ No newline at end of file
diff --git a/src/pages/api/payments/assigned.ts b/src/pages/api/payments/assigned.ts
new file mode 100644
index 00000000..107e619e
--- /dev/null
+++ b/src/pages/api/payments/assigned.ts
@@ -0,0 +1,81 @@
+// 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,
+ query,
+ where,
+} from "firebase/firestore";
+import { withIronSessionApiRoute } from "iron-session/next";
+import { sessionOptions } from "@/lib/session";
+import { Payment } from "@/interfaces/paypal";
+import { PaymentsStatus } from "@/interfaces/user.payments";
+
+const db = getFirestore(app);
+
+export default withIronSessionApiRoute(handler, sessionOptions);
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ if (req.method === "GET") return await get(req, res);
+
+ res.status(404).json(undefined);
+}
+
+// user can fetch payments assigned to him as an agent
+async function get(req: NextApiRequest, res: NextApiResponse) {
+ if (!req.session.user) {
+ res.status(401).json({ ok: false });
+ return;
+ }
+
+ const codeQuery = query(
+ collection(db, "payments"),
+ // where("agent", "==", "xRMirufz6PPQqxKBgvPTWiWKBD63"),
+ where(req.session.user.type, "==", req.session.user.id)
+ // Based on the logic of query we should be able to do this:
+ // where("isPaid", "==", paid === "paid"),
+ // but for some reason it is ignoring all but the first clause
+ // I opted into only fetching relevant content for the user
+ // and then filter it with JS
+ );
+
+ const snapshot = await getDocs(codeQuery);
+ if (snapshot.empty) {
+ res.status(200).json({
+ pending: [],
+ done: [],
+ });
+ return;
+ }
+
+ const docs = snapshot.docs.map((doc) => ({
+ id: doc.id,
+ ...doc.data(),
+ })) as Payment[];
+
+ const paidStatusEntries = docs.reduce(
+ (acc: PaymentsStatus, doc) => {
+ if (doc.isPaid) {
+ return {
+ ...acc,
+ done: [...acc.done, doc.corporate],
+ };
+ }
+
+ return {
+ ...acc,
+ pending: [...acc.pending, doc.corporate],
+ };
+ },
+ {
+ pending: [],
+ done: [],
+ }
+ );
+ res.status(200).json({
+ pending: [...new Set(paidStatusEntries.pending)],
+ done: [...new Set(paidStatusEntries.done)],
+ });
+}