diff --git a/apps/back-office/components/footer-buttons/footer-buttons.tsx b/apps/back-office/components/footer-buttons/footer-buttons.tsx index 0afac22c6..4073da62d 100644 --- a/apps/back-office/components/footer-buttons/footer-buttons.tsx +++ b/apps/back-office/components/footer-buttons/footer-buttons.tsx @@ -1,14 +1,17 @@ import { CheckIcon, XIcon } from '@heroicons/react/outline'; import api from '../../utils/api'; import router from 'next/router'; +import Modal from '../modal/modal'; import APP_CONSTANTS, { API_ROUTE, ENROLLMENT_TYPE, ROUTE_CONSTANTS, } from '../../utils/constants'; import { toast } from 'react-toastify'; +import { useState } from 'react'; export function FooterButtons(props) { + const [openModal, setOpenModal] = useState(false); const saveButtonClassName = props.disableSave ? 'shadow-special-button-default inline-flex w-full justify-center rounded-full bg-slate-400 px-6 py-2 text-base font-semibold leading-6 text-white outline-none' : 'on-focus leading-3.5 text-md mb-2 mr-2 flex items-center rounded-full border border-blue-600 bg-blue-600 px-4 py-3 text-left font-medium text-white last:mr-0 focus-within:rounded-full hover:border-slate-400 focus:rounded-full focus-visible:rounded-full'; @@ -28,11 +31,16 @@ export function FooterButtons(props) { try { let message = ""; setLoader(true); - await api.patch(`${API_ROUTE.PARTICIPANTS_REQUEST}/${id}`, data, configuration) - message = status === "REJECTED" - ? `Successfully ${APP_CONSTANTS.REJECTED_LABEL}` - : `Successfully ${isVerified ? APP_CONSTANTS.VERIFIED_FLAG : APP_CONSTANTS.UNVERIFIED_FLAG}`; - + if (props.from === "approved") { + await api.post(`${API_ROUTE.ADMIN_APPROVAL}`, { memberIds: [props.id] }, configuration); + message = `Successfully ${APP_CONSTANTS.VERIFIED_FLAG}`; + } else { + await api.patch(`${API_ROUTE.PARTICIPANTS_REQUEST}/${id}`, data, configuration) + message = status === "REJECTED" + ? `Successfully ${APP_CONSTANTS.REJECTED_LABEL}` + : `Successfully ${isVerified ? APP_CONSTANTS.VERIFIED_FLAG : APP_CONSTANTS.UNVERIFIED_FLAG}`; + } + setOpenModal(false) toast(message); router.push({ pathname: ROUTE_CONSTANTS.PENDING_LIST, @@ -48,12 +56,64 @@ export function FooterButtons(props) { toast(error.message || 'An unexpected error occurred'); } } finally { + setOpenModal(false) setLoader(false); } } + const handleOpen = () => { + setOpenModal(true); + } + + const onClose = () => { + setOpenModal(false); + } + return (
+ {openModal && + +
+
+ +
+
+
+ Are you sure you want to reject? +
+
+ Clicking remove will remove the member from the list. +
+ +
+ + + +
+
+
+
+ } diff --git a/apps/back-office/components/member-table/member-table.tsx b/apps/back-office/components/member-table/member-table.tsx index bd5ec1fb7..cb571520e 100644 --- a/apps/back-office/components/member-table/member-table.tsx +++ b/apps/back-office/components/member-table/member-table.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import Loader from '../common/loader'; import { useNavbarContext } from 'apps/back-office/context/navbar-context'; +import Modal from '../modal/modal'; const MemberTable = (props: any) => { const selectedTab = props?.selectedTab ?? ''; @@ -16,6 +17,9 @@ const MemberTable = (props: any) => { const [isLoading, setIsLoading] = useState(false); const [isSort, setIsSort] = useState(false); const { setMemberList } = useNavbarContext(); + const [openModal, setOpenModal] = useState(false); + const [rejectId, setRejectId] = useState([]); + // const onSortClickHandler = () => { // setIsSort(!isSort); @@ -58,7 +62,7 @@ const MemberTable = (props: any) => { function redirectToDetail(request) { setIsLoading(true); const route = ROUTE_CONSTANTS.MEMBER_VIEW; - const from = selectedTab === APP_CONSTANTS.PENDING_FLAG ? "pending": "approved"; + const from = selectedTab === APP_CONSTANTS.PENDING_FLAG ? "pending" : "approved"; router.push({ pathname: route, query: { @@ -86,7 +90,7 @@ const MemberTable = (props: any) => { setIsLoading(true); if (selectedTab === APP_CONSTANTS.PENDING_FLAG) { await api.post(`${API_ROUTE.PARTICIPANTS_REQUEST}`, [data], configuration); - message = `Successfully ${(status === APP_CONSTANTS.REJECTED_FLAG ? APP_CONSTANTS.REJECTED_LABEL : (isVerified ? APP_CONSTANTS.VERIFIED_FLAG : APP_CONSTANTS.UNVERIFIED_FLAG))}`; + message = `Successfully ${(status === APP_CONSTANTS.REJECTED_FLAG ? APP_CONSTANTS.REJECTED_LABEL : (isVerified ? APP_CONSTANTS.VERIFIED_FLAG : APP_CONSTANTS.UNVERIFIED_FLAG))}`; } else { await api.post(`${API_ROUTE.ADMIN_APPROVAL}`, { memberIds: [id] }, configuration); message = `Successfully ${APP_CONSTANTS.VERIFIED_FLAG}`; @@ -171,6 +175,7 @@ const MemberTable = (props: any) => { setSelectedMembes([]); setIsAllSelected(false); const message = `Successfully ${APP_CONSTANTS.REJECTED_LABEL}`; + setOpenModal(false) toast(message); } catch (error: any) { if (error.response?.status === 500) { @@ -183,22 +188,35 @@ const MemberTable = (props: any) => { toast(error.message || 'An unexpected error occurred'); } } finally { + setOpenModal(false); setIsLoading(false); } }; + const handleOpen = (id: any) => { + setOpenModal(true); + if (Array.isArray(id)) { + setRejectId(id); + } else { + setRejectId(id); + } + } + + const onClose = () => { + setOpenModal(false); + } + return ( <> {isLoading && } {allMembers?.length > 0 && ( -
+
{/* Header */}
- - {selectedTab === APP_CONSTANTS.PENDING_FLAG && ( )} + + {selectedTab === APP_CONSTANTS.PENDING_FLAG && ( )}
@@ -326,36 +340,81 @@ const MemberTable = (props: any) => {
- - {selectedTab === APP_CONSTANTS.PENDING_FLAG && ( )} + + {selectedTab === APP_CONSTANTS.PENDING_FLAG && ( )}
)} + + {openModal && + +
+
+ +
+
+
+ Are you sure you want to reject? +
+
+ Clicking remove will remove the member from the list. +
+ +
+ + + +
+
+
+
+ } ); }; diff --git a/apps/back-office/pages/member-view.tsx b/apps/back-office/pages/member-view.tsx index 41758e572..7f9df3ef7 100644 --- a/apps/back-office/pages/member-view.tsx +++ b/apps/back-office/pages/member-view.tsx @@ -85,7 +85,7 @@ export default function MemberView(props) { const [disableSave, setDisableSave] = useState(false); const [formValues, setFormValues] = useState(props?.formValues); const [isLoading, setIsLoading] = useState(false); - const [resetImg, setResetImg] = useState(false); + const [resetImg, setResetImg] = useState(false); const { setIsOpenRequest, setMemberList, @@ -102,7 +102,7 @@ export default function MemberView(props) { useEffect(() => { setDropDownValues({ skillValues: props?.skills, teamNames: props?.teams }); }, [props]); - + const handleResetImg = () => { setResetImg(false); } @@ -128,7 +128,7 @@ export default function MemberView(props) { twitterHandler: formValues.twitterHandler?.trim(), githubHandler: formValues.githubHandler?.trim(), telegramHandler: formValues.telegramHandler?.trim(), - officeHours: formValues.officeHours?.trim() === ''? null : formValues.officeHours?.trim(), + officeHours: formValues.officeHours?.trim() === '' ? null : formValues.officeHours?.trim(), comments: formValues.comments?.trim(), teamOrProjectURL: formValues.teamOrProjectURL, plnStartDate: formValues.plnStartDate @@ -137,7 +137,7 @@ export default function MemberView(props) { skills: skills, teamAndRoles: formattedTeamAndRoles, openToWork: formValues.openToWork, - projectContributions:formValues.projectContributions, + projectContributions: formValues.projectContributions, oldName: name, }; delete formattedData.requestorEmail; @@ -212,13 +212,25 @@ export default function MemberView(props) { imageUrl: image?.url ?? imageUrl, }, }; - const configuration = { + const configuration = { headers: { authorization: `Bearer ${props.plnadmin}`, }, }; - await api + if(props?.from === "approved") { + await api.patch( + `${API_ROUTE.ADMIN_APPROVAL}/${props.id}`, + data, + configuration + ) + .then((response) => { + setSaveCompleted(true); + setIsEditEnabled(false); + setResetImg(true); + }); + } else { + await api .put( `${API_ROUTE.PARTICIPANTS_REQUEST}/${props.id}`, data, @@ -229,6 +241,7 @@ export default function MemberView(props) { setIsEditEnabled(false); setResetImg(true); }); + } } catch (err) { toast(err?.message); console.log('error', err); @@ -386,6 +399,7 @@ export default function MemberView(props) { referenceUid={props.referenceUid} setLoader={setIsLoading} token={props.plnadmin} + from={props.from} /> )} @@ -393,9 +407,10 @@ export default function MemberView(props) { } export const getServerSideProps = async (context) => { - const { id, backLink = ROUTE_CONSTANTS.PENDING_LIST } = context.query as { + const { id, from, backLink = ROUTE_CONSTANTS.PENDING_LIST } = context.query as { id: string; backLink: string; + from: string; }; const { plnadmin } = parseCookies(context); @@ -421,119 +436,162 @@ export const getServerSideProps = async (context) => { let teamList = []; let oldName = ''; - // Check if provided ID is an Airtable ID, and if so, get the corresponding backend UID - - const [ - requestDetailResponse, - allRequestResponse, - memberTeamsResponse, - skillsResponse, - ] = await Promise.all([ - api.get(`${API_ROUTE.PARTICIPANTS_REQUEST}/${id}`, config), - api.get(API_ROUTE.PARTICIPANTS_REQUEST, config), - api.get(API_ROUTE.TEAMS), - api.get(API_ROUTE.SKILLS), - ]); - - if ( - requestDetailResponse.status === 200 && - allRequestResponse.status === 200 && - memberTeamsResponse.status === 200 && - skillsResponse.status === 200 - ) { - teamList = allRequestResponse?.data?.filter( - (item) => item.participantType === ENROLLMENT_TYPE.TEAM - ); - memberList = allRequestResponse?.data?.filter( - (item) => item.participantType === ENROLLMENT_TYPE.MEMBER - ); + + if (from !== "approved") { + const [ + requestDetailResponse, + allRequestResponse, + memberTeamsResponse, + skillsResponse, + ] = await Promise.all([ + api.get(`${API_ROUTE.PARTICIPANTS_REQUEST}/${id}`, config), + api.get(API_ROUTE.PARTICIPANTS_REQUEST, config), + api.get(API_ROUTE.TEAMS), + api.get(API_ROUTE.SKILLS), + ]); - let counter = 1; - referenceUid = requestDetailResponse?.data?.referenceUid ?? ''; - const requestData = requestDetailResponse?.data?.newData; - oldName = requestData?.oldName ?? requestData?.name; - status = requestDetailResponse?.data?.status; - const teamAndRoles = - requestData?.teamAndRoles?.length && - requestData?.teamAndRoles?.map((team) => { - return { - role: team.role ?? "", - teamUid: team.teamUid, - teamTitle: team.teamTitle, - rowId: counter++, - }; - }); - - formValues = { - name: requestData?.name, - email: requestData?.email, - imageUid: requestData?.imageUid ?? '', - imageFile: null, - plnStartDate: requestData?.plnStartDate - ? new Date(requestData?.plnStartDate).toISOString().split('T')[0] - : null, - city: requestData?.city ?? '', - region: requestData?.region ?? '', - country: requestData?.country ?? '', - linkedinHandler: requestData?.linkedinHandler ?? '', - discordHandler: requestData?.discordHandler ?? '', - twitterHandler: requestData?.twitterHandler ?? '', - githubHandler: requestData?.githubHandler ?? '', - telegramHandler: requestData?.telegramHandler ?? '', - officeHours: requestData?.officeHours ?? '', - requestorEmail: requestDetailResponse?.data?.requesterEmailId ?? '', - comments: requestData?.comments ?? '', - teamAndRoles: teamAndRoles || [ - // { teamUid: '', teamTitle: '', role: '', rowId: 1 }, - ], - teamOrProjectURL: requestData?.teamOrProjectURL ?? '', - skills: requestData?.skills?.map((item) => { + if ( + requestDetailResponse.status === 200 && + allRequestResponse.status === 200 && + memberTeamsResponse.status === 200 && + skillsResponse.status === 200 + ) { + teamList = allRequestResponse?.data?.filter( + (item) => item.participantType === ENROLLMENT_TYPE.TEAM + ); + memberList = allRequestResponse?.data?.filter( + (item) => item.participantType === ENROLLMENT_TYPE.MEMBER + ); + + let counter = 1; + referenceUid = requestDetailResponse?.data?.referenceUid ?? ''; + const requestData = requestDetailResponse?.data?.newData; + oldName = requestData?.oldName ?? requestData?.name; + status = requestDetailResponse?.data?.status; + const teamAndRoles = + requestData?.teamAndRoles?.length && + requestData?.teamAndRoles?.map((team) => { + return { + role: team.role ?? "", + teamUid: team.teamUid, + teamTitle: team.teamTitle, + rowId: counter++, + }; + }); + + formValues = { + name: requestData?.name, + email: requestData?.email, + imageUid: requestData?.imageUid ?? '', + imageFile: null, + plnStartDate: requestData?.plnStartDate + ? new Date(requestData?.plnStartDate).toISOString().split('T')[0] + : null, + city: requestData?.city ?? '', + region: requestData?.region ?? '', + country: requestData?.country ?? '', + linkedinHandler: requestData?.linkedinHandler ?? '', + discordHandler: requestData?.discordHandler ?? '', + twitterHandler: requestData?.twitterHandler ?? '', + githubHandler: requestData?.githubHandler ?? '', + telegramHandler: requestData?.telegramHandler ?? '', + officeHours: requestData?.officeHours ?? '', + requestorEmail: requestDetailResponse?.data?.requesterEmailId ?? '', + comments: requestData?.comments ?? '', + teamAndRoles: teamAndRoles || [ + // { teamUid: '', teamTitle: '', role: '', rowId: 1 }, + ], + teamOrProjectURL: requestData?.teamOrProjectURL ?? '', + skills: requestData?.skills?.map((item) => { + return { value: item.uid, label: item.title }; + }) || [], + openToWork: requestData?.openToWork ?? '', + projectContributions: requestData?.projectContributions ?? [] + }; + imageUrl = requestData?.imageUrl ?? ''; + + if (status == APP_CONSTANTS.PENDING_LABEL) { + teamList = allRequestResponse?.data + ?.filter((item) => item.participantType === ENROLLMENT_TYPE.TEAM) + ?.filter((item) => item.status === APP_CONSTANTS.PENDING_LABEL); + memberList = allRequestResponse?.data + ?.filter((item) => item.participantType === ENROLLMENT_TYPE.MEMBER) + .filter((item) => item.status === APP_CONSTANTS.PENDING_LABEL); + } else { + teamList = allRequestResponse?.data + ?.filter((item) => item.participantType === ENROLLMENT_TYPE.TEAM) + ?.filter((item) => item.status !== APP_CONSTANTS.PENDING_LABEL); + memberList = allRequestResponse?.data + ?.filter((item) => item.participantType === ENROLLMENT_TYPE.MEMBER) + .filter((item) => item.status !== APP_CONSTANTS.PENDING_LABEL); + } + + teams = Array.isArray(memberTeamsResponse?.data) ? + memberTeamsResponse?.data?.map((item) => { + return { value: item.uid, label: item.name }; + }) : []; + skills = skillsResponse?.data?.map((item) => { return { value: item.uid, label: item.title }; - }), - openToWork: requestData?.openToWork ?? '', - projectContributions:requestData?.projectContributions ?? [] - }; - imageUrl = requestData?.imageUrl ?? ''; - - if (status == APP_CONSTANTS.PENDING_LABEL) { - teamList = allRequestResponse?.data - ?.filter((item) => item.participantType === ENROLLMENT_TYPE.TEAM) - ?.filter((item) => item.status === APP_CONSTANTS.PENDING_LABEL); - memberList = allRequestResponse?.data - ?.filter((item) => item.participantType === ENROLLMENT_TYPE.MEMBER) - .filter((item) => item.status === APP_CONSTANTS.PENDING_LABEL); - } else { - teamList = allRequestResponse?.data - ?.filter((item) => item.participantType === ENROLLMENT_TYPE.TEAM) - ?.filter((item) => item.status !== APP_CONSTANTS.PENDING_LABEL); - memberList = allRequestResponse?.data - ?.filter((item) => item.participantType === ENROLLMENT_TYPE.MEMBER) - .filter((item) => item.status !== APP_CONSTANTS.PENDING_LABEL); + }); } + } else { + const approvedApiResponse = await api.get(`${API_ROUTE.MEMBERS}/${id}`, config); - teams = Array.isArray(memberTeamsResponse?.data) ? - memberTeamsResponse?.data?.map((item) => { - return { value: item.uid, label: item.name }; - }) : []; - skills = skillsResponse?.data?.map((item) => { - return { value: item.uid, label: item.title }; - }); - } + if (approvedApiResponse.status === 200) { + const requestData = approvedApiResponse?.data; + formValues = { + name: requestData?.name, + email: requestData?.email, + imageUid: requestData?.imageUid ?? '', + imageFile: null, + plnStartDate: requestData?.plnStartDate + ? new Date(requestData?.plnStartDate).toISOString().split('T')[0] + : null, + city: requestData?.city ?? '', + region: requestData?.region ?? '', + country: requestData?.country ?? '', + linkedinHandler: requestData?.linkedinHandler ?? '', + discordHandler: requestData?.discordHandler ?? '', + twitterHandler: requestData?.twitterHandler ?? '', + githubHandler: requestData?.githubHandler ?? '', + telegramHandler: requestData?.telegramHandler ?? '', + officeHours: requestData?.officeHours ?? '', + comments: requestData?.comments ?? '', + teamAndRoles: // teamAndRoles || + [ + // { teamUid: '', teamTitle: '', role: '', rowId: 1 }, + ], + teamOrProjectURL: requestData?.teamOrProjectURL ?? '', + skills: requestData?.skills?.map((item) => { + return { value: item.uid, label: item.title }; + }), + openToWork: requestData?.openToWork ?? '', + projectContributions: requestData?.projectContributions ?? [] + }; + imageUrl = requestData?.imageUrl ?? ''; + teamList = approvedApiResponse?.data?.teamList ?? []; + memberList = approvedApiResponse?.data?.memberList ?? []; + teams = approvedApiResponse?.data?.teams ?? []; + skills = approvedApiResponse?.data?.skills ?? []; + status= APP_CONSTANTS.PENDING_LABEL; + } + } - return { - props: { - formValues, - teams, - skills, - id, - referenceUid, - imageUrl, - status, - backLink, - teamList, - memberList, - plnadmin, - oldName, - }, + return { + props: { + formValues, + teams, + skills, + id, + // referenceUid, + imageUrl, + status, + backLink, + teamList, + memberList, + plnadmin, + oldName, + from, + }, + }; }; -};