diff --git a/src/app/about/clubs-council/cc-members/page.jsx b/src/app/about/clubs-council/cc-members/page.jsx index 4c6a3b27..e5f4c9b6 100644 --- a/src/app/about/clubs-council/cc-members/page.jsx +++ b/src/app/about/clubs-council/cc-members/page.jsx @@ -19,7 +19,7 @@ export default async function AllMembers() { }, }); - const techMembers = members + const ccMembers = members ?.map((member) => { const { roles } = member; const techTeamRoles = filterRoles(roles, techTeamWords); @@ -30,11 +30,11 @@ export default async function AllMembers() { return member.roles.length > 0; }); - const currentYear = (new Date().getFullYear() + 1).toString(); + // const currentYear = (new Date().getFullYear() + 1).toString(); // construct dict of { year: [members] } where each year is a key - const targetMembers = techMembers - ? techMembers.reduce((acc, member) => { + const targetMembers = ccMembers + ? ccMembers.reduce((acc, member) => { const latestYear = extractFirstYear(member); if (!acc[latestYear]) { acc[latestYear] = []; @@ -52,7 +52,7 @@ export default async function AllMembers() { - {techMembers?.length ? ( + {ccMembers?.length ? ( Object.keys(targetMembers) ?.sort((a, b) => { if (a === -1) { diff --git a/src/app/about/clubs-council/tech-members/page.jsx b/src/app/about/clubs-council/tech-members/page.jsx index b43476f5..7017c72d 100644 --- a/src/app/about/clubs-council/tech-members/page.jsx +++ b/src/app/about/clubs-council/tech-members/page.jsx @@ -30,7 +30,7 @@ export default async function TechTeam() { return member.roles.length > 0; }); - const currentYear = (new Date().getFullYear() + 1).toString(); + // const currentYear = (new Date().getFullYear() + 1).toString(); // construct dict of { year: [members] } where each year is a key const targetMembers = techMembers diff --git a/src/app/actions/events/progress/route.jsx b/src/app/actions/events/progress/route.jsx index 310c96dd..6c42cc0c 100644 --- a/src/app/actions/events/progress/route.jsx +++ b/src/app/actions/events/progress/route.jsx @@ -5,13 +5,14 @@ import { PROGRESS_EVENT } from "gql/mutations/events"; export async function POST(request) { const response = { ok: false, error: null }; - const { eventid, cc_progress_budget, cc_progress_room } = + const { eventid, cc_progress_budget, cc_progress_room, cc_approver } = await request.json(); const { error } = await getClient().mutation(PROGRESS_EVENT, { eventid, ccProgressBudget: cc_progress_budget, ccProgressRoom: cc_progress_room, + ccApprover: cc_approver, }); if (error) { response.error = { diff --git a/src/app/manage/events/[id]/approve_cc/page.jsx b/src/app/manage/events/[id]/approve_cc/page.jsx new file mode 100644 index 00000000..e1146c3b --- /dev/null +++ b/src/app/manage/events/[id]/approve_cc/page.jsx @@ -0,0 +1,79 @@ +import { getClient } from "gql/client"; +import { GET_USER } from "gql/queries/auth"; +import { GET_MEMBERS } from "gql/queries/members"; +import { GET_FULL_EVENT } from "gql/queries/events"; +import { redirect } from "next/navigation"; + +import { Container, Typography } from "@mui/material"; + +import { techTeamWords } from "constants/ccMembersFilterWords"; +import { extractFirstYear } from "components/members/MembersGrid"; +import EventApproveForm from "components/events/EventApproveForm"; + +export const metadata = { + title: "Approve Event | CC", +}; + +export default async function ApproveEventCC({ params }) { + const { id } = params; + const { data: { event } = {} } = await getClient().query(GET_FULL_EVENT, { + eventid: id, + }); + const { data: { userMeta, userProfile } = {} } = await getClient().query( + GET_USER, + { userInput: null } + ); + const user = { ...userMeta, ...userProfile }; + + const { data: { members } = {} } = await getClient().query(GET_MEMBERS, { + clubInput: { + cid: "cc", + }, + }); + + const ccMembers = members + ?.map((member) => { + const { roles } = member; + const techTeamRoles = filterRoles(roles, techTeamWords); + const newMember = { ...member, roles: techTeamRoles }; + return newMember; + }) + ?.filter((member) => { + return member.roles.length > 0; + }); + + // construct dict of { year: [members] } where each year is a key + const currentccMembers = ccMembers + ? ccMembers.filter((member) => { + const latestYear = extractFirstYear(member); + if (latestYear === -1) { + return true; + } + return false; + }) + : []; + + return ( + user?.role !== "cc" && redirect("/404"), + event?.status?.state !== "pending_cc" && redirect("/404"), + ( + +
+ + Approve Event | Clubs Council + +
+ + +
+ ) + ); +} + +const filterRoles = (roles, filterWords) => { + return roles?.filter((role) => { + const { name } = role; + const lowercaseName = name.toLowerCase(); + return !filterWords.some((word) => lowercaseName.includes(word)); + }); +}; diff --git a/src/components/events/EventActions.jsx b/src/components/events/EventActions.jsx index add6a2cb..61207e18 100644 --- a/src/components/events/EventActions.jsx +++ b/src/components/events/EventActions.jsx @@ -5,7 +5,7 @@ import { useRouter, useParams } from "next/navigation"; import { useState } from "react"; -import { Box, Button, Checkbox, FormControlLabel } from "@mui/material"; +import { Button } from "@mui/material"; import Icon from "components/Icon"; import ConfirmDialog from "components/ConfirmDialog"; @@ -152,38 +152,6 @@ export function ApproveEvent({ sx }) { const { triggerToast } = useToast(); const [dialog, setDialog] = useState(false); - // approval checks - const [SLC, setSLC] = useState(false); - const [SLO, setSLO] = useState(false); - - const approvalDialog = - user?.role === "cc" ? ( - - setSLC(e.target.checked)} - color="success" - /> - } - label="Request SLC approval" - /> - setSLO(e.target.checked)} - color="success" - /> - } - label="Request SLO approval" - /> - - ) : ( - "This action cannot be undone." - ); - const approveEvent = async () => { // console.log("requested approvals:", SLC, SLO); let res = await fetch("/actions/events/progress", { @@ -192,6 +160,7 @@ export function ApproveEvent({ sx }) { eventid: id, cc_progress_budget: !SLC, cc_progress_room: !SLO, + cc_approver: null, }), }); res = await res.json(); @@ -215,25 +184,41 @@ export function ApproveEvent({ sx }) { return ( <> - - - setDialog(false)} - confirmProps={{ color: "success" }} - confirmText="Yes, approve it" - /> + {/* If user?.role === "cc", then redirect to /manage/events/id/approve_cc */} + {user && user.role === "cc" ? ( + + ) : ( + <> + + + setDialog(false)} + confirmProps={{ color: "success" }} + confirmText="Yes, approve it" + /> + + )} ); } diff --git a/src/components/events/EventApproveForm.jsx b/src/components/events/EventApproveForm.jsx new file mode 100644 index 00000000..4cdba5a6 --- /dev/null +++ b/src/components/events/EventApproveForm.jsx @@ -0,0 +1,154 @@ +"use client"; + +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { useForm, Controller } from "react-hook-form"; + +import Icon from "components/Icon"; +import { useToast } from "components/Toast"; +import MemberListItem from "components/members/MemberListItem"; + +import { LoadingButton } from "@mui/lab"; +import { + Box, + Checkbox, + Fade, + CircularProgress, + Typography, + FormControlLabel, + FormHelperText, + FormControl, + InputLabel, + Select, + MenuItem, +} from "@mui/material"; + +export default function EventApproveForm({ event, members }) { + const { triggerToast } = useToast(); + const router = useRouter(); + + const [loading, setLoading] = useState(false); + + const { control, handleSubmit } = useForm({ + defaultValues: { + SLC: false, + SLO: false, + }, + }); + + async function handleApprove(formData) { + let cc_progress_budget = !formData.SLC; + let cc_progress_room = !formData.SLO; + let approver = formData.approver; + + console.log(cc_progress_budget, cc_progress_room, approver); + setLoading(true); + + let res = await fetch("/actions/events/progress", { + method: "POST", + body: JSON.stringify({ + eventid: event._id, + cc_progress_budget: cc_progress_budget, + cc_progress_room: cc_progress_room, + cc_approver: approver, + }), + }); + if (res.ok) { + triggerToast("Event approved", "success"); + router.push(`/manage/events/${event._id}`); + router.refresh(); + } else { + triggerToast({ + ...res.error, + severity: "error", + }); + } + } + + return ( + <> +
+ ( + + } + label="Request SLC approval" + /> + )} + /> +

{/* For New line */} + ( + + } + label="Request SLO approval" + /> + )} + /> +

{/* For New line */} + ( + + Approver + {members.length === 0 ? ( + + + + + + ) : ( + + )} + {error?.message} + + )} + /> +

{/* For New line */} + } + // fullWidth + > + Approve + + + (This action cannot be undone.) + + + + ); +} diff --git a/src/gql/mutations/events.jsx b/src/gql/mutations/events.jsx index 71be16e4..3c739ca4 100644 --- a/src/gql/mutations/events.jsx +++ b/src/gql/mutations/events.jsx @@ -29,11 +29,13 @@ export const PROGRESS_EVENT = gql` $eventid: String! $ccProgressBudget: Boolean $ccProgressRoom: Boolean + $ccApprover: String ) { progressEvent( eventid: $eventid ccProgressBudget: $ccProgressBudget ccProgressRoom: $ccProgressRoom + ccApprover: $ccApprover ) { _id }