Skip to content

Commit

Permalink
Merge pull request #434 from NIAEFEUP/fix/schedule-issues
Browse files Browse the repository at this point in the history
Fix/schedule issues
  • Loading branch information
tomaspalma authored Feb 6, 2025
2 parents aa95835 + bc40f97 commit 450a263
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 18 deletions.
5 changes: 4 additions & 1 deletion src/components/admin/requests/AdminSendEmail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ type Props = {
nmec: string | Array<string>
}

/**
* This component is so that the admin can send an email to the users without a pre defined subject and body.
*/
export const AdminSendEmail = ({
nmec
}: Props) => {
return <>
<a href={`${mailtoStringBuilder(nmec)}?subject=Pedido de Inscrição em Turmas&[email protected]&body=Viva,%0D%0A%0D%0AForam alocadas turmas nas UCs indicadas.%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`}>
<a href={`${mailtoStringBuilder(nmec)}[email protected]&body=Viva,%0D%0A%0D%0A %0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`}>
<Button
variant="secondary"
>
Expand Down
17 changes: 14 additions & 3 deletions src/components/admin/requests/cards/AdminRequestCardFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Dispatch, SetStateAction } from "react"
import { AdminRequestType, CourseUnitEnrollment, DirectExchangeRequest, UrgentRequest } from "../../../../@types"
import { CourseUnitEnrollment, DirectExchangeRequest, UrgentRequest } from "../../../../@types"
import { AdminRequestType } from "../../../../utils/exchange"
import exchangeRequestService from "../../../../api/services/exchangeRequestService"
import { mailtoStringBuilder } from "../../../../utils/mail"
import { Button } from "../../../ui/button"
Expand Down Expand Up @@ -28,7 +29,12 @@ const rejectRequest = async (
await exchangeRequestService.adminRejectExchangeRequest(requestType, id);

const a = document.createElement('a');
a.href = `${mailtoStringBuilder(nmecs)}?subject=Pedido de Alteração de Turma&[email protected]&body=Viva,%0D%0A%0D%0AA alteração pedida não pode ser efetuada.%0D%0A${exchangeMessage}%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`;
if(requestType === AdminRequestType.DIRECT_EXCHANGE || requestType === AdminRequestType.URGENT_EXCHANGE) {
a.href = `${mailtoStringBuilder(nmecs)}?subject=Pedido de Alteração de Turma&[email protected]&body=Viva,%0D%0A%0D%0AA alteração pedida não pode ser efetuada.%0D%0A${exchangeMessage}%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`;
} else {
a.href = `${mailtoStringBuilder(nmecs)}?subject=Pedido de Inscrição em Unidades Curriculares&[email protected]&body=Viva,%0D%0A%0D%0AO pedido de inscriçao em unidades curriculares não pode ser efetuado..%0D%0A${exchangeMessage}%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`;
}

a.click();
} catch (e) {
console.error(e);
Expand All @@ -45,7 +51,11 @@ const acceptRequest = async (
await exchangeRequestService.adminAcceptExchangeRequest(requestType, id);

const a = document.createElement('a');
a.href = `${mailtoStringBuilder(nmecs)}?subject=Pedido de Troca de Turma&[email protected]&body=Viva,%0D%0A%0D%0AA alteração pedida foi efetuada.%0D%0A${exchangeMessage}%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`;
if(requestType === AdminRequestType.DIRECT_EXCHANGE || requestType === AdminRequestType.URGENT_EXCHANGE) {
a.href = `${mailtoStringBuilder(nmecs)}?subject=Pedido de Troca de Turma&[email protected]&body=Viva,%0D%0A%0D%0AA alteração pedida foi efetuada.%0D%0A${exchangeMessage}%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`;
} else {
a.href = `${mailtoStringBuilder(nmecs)}?subject=Pedido de Inscrição em Unidades Curriculares&[email protected]&body=Viva,%0D%0A%0D%0AA alteração pedida foi efetuada.%0D%0A${exchangeMessage}%0D%0A%0D%0ACmpts,%0D%0ADaniel Silva%0D%0A(pela comissão de inscrição em turmas)`;
}
a.click();
} catch (e) {
console.error(e);
Expand All @@ -69,6 +79,7 @@ export const AdminRequestCardFooter = ({
setExchange,
courseId
}: Props) => {

return <>
<Separator className="my-4" />
<CardFooter className="justify-end gap-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ export const MultipleStudentExchangeCard = ({
{open &&
<AdminRequestCardFooter
nmecs={
exchange.options.map(option => option.participant_nmec)
[...new Set(exchange.options.map(option => option.participant_nmec))]
}
exchangeMessage={listEmailExchanges(
exchange.options.map(option => ({
participant_nmec: option.participant_nmec,
goes_from: option.class_participant_goes_from.name,
goes_to: option.class_participant_goes_to.name,
course_acronym: option.course_unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const SingleStudentExchangeCard = ({
nmecs={[exchange.user_nmec]}
exchangeMessage={listEmailExchanges(
exchange.options.map(option => ({
participant_nmec: exchange.user_nmec,
goes_from: option.class_user_goes_from.name,
goes_to: option.class_user_goes_to.name,
course_acronym: option.course_unit.acronym
Expand Down
12 changes: 11 additions & 1 deletion src/components/admin/requests/cards/StudentEnrollmentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useStudentsSchedule from "../../../../hooks/admin/useStudentsSchedule"
import { RequestDate } from "./RequestDate"
import { AdminRequestType } from "../../../../utils/exchange"
import { ExchangeStatus } from "./ExchangeStatus"
import { listEmailEnrollments } from "../../../../utils/mail"

type Props = {
enrollment: CourseUnitEnrollment
Expand Down Expand Up @@ -109,7 +110,16 @@ export const StudentEnrollmentCard = ({
{open &&
<AdminRequestCardFooter
nmecs={[enrollment.user_nmec]}
exchangeMessage={""}
exchangeMessage={
listEmailEnrollments(
enrollment.options.map(option => ({
participant_nmec: enrollment.user_nmec,
goes_to: option.course_unit.name,
course: option.course_unit.course,
course_unit_id: option.course_unit.id
}))
)
}
requestType={AdminRequestType.ENROLLMENT}
requestId={enrollment.id}
setExchange={setEnrollmentState}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ export const CommonCardHeader = ({
? StudentRequestCardStatus.ACCEPTED
: StudentRequestCardStatus.PENDING
);

if(request.type === "directexchange") {
(request as DirectExchangeRequest).options = (request as DirectExchangeRequest).options.filter((option) => option.participant_nmec === username);
}
}, [request]);


return <CardHeader
className="flex flex-row gap-x-2 items-center p-4"
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/exchange/verify/ExchangeVerifyStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type Props = {
export const ExchangeVerifyStatus = ({
verified
}: Props) => {
return (<div className="flex flex-col items-center gap-y-2">
return (<div className="my-auto flex flex-col items-center gap-y-2">
{verified
? <>
<Check size={100} />
Expand Down
4 changes: 2 additions & 2 deletions src/contexts/CombinedProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const CombinedProvider = ({ children }: Props) => {
const [multipleOptions, setMultipleOptionsState] = useState<MultipleOptions>(StorageAPI.getMultipleOptionsStorage());
const [selectedOption, setSelectedOptionState] = useState<number>(StorageAPI.getSelectedOptionStorage());

const { signedIn: userSignedIn, user, isLoading: isSessionLoading } = useSession();
const { signedIn: userSignedIn, user, isLoading: isSessionLoading, forceScheduleRevalidation } = useSession();
const [signedIn, setSignedIn] = useState<boolean>(Boolean(localStorage.getItem("signedIn") ?? false));
useEffect(() => {
setSignedIn(userSignedIn);
Expand All @@ -53,7 +53,7 @@ const CombinedProvider = ({ children }: Props) => {
}

return (
<SessionContext.Provider value={{ signedIn, setSignedIn, user, isSessionLoading }}>
<SessionContext.Provider value={{ signedIn, setSignedIn, user, isSessionLoading, forceScheduleRevalidation }}>
<ThemeContext.Provider value={{ enabled, setEnabled }}>
<MajorContext.Provider value={{ majors, setMajors }}>
<CourseContext.Provider value={
Expand Down
4 changes: 3 additions & 1 deletion src/contexts/SessionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ interface SessionContextContent {
user: any
isSessionLoading: boolean
setSignedIn: Dispatch<SetStateAction<boolean>>
forceScheduleRevalidation: () => void
}

const SessionContext: Context<SessionContextContent> = createContext({
signedIn: false,
user: null,
isSessionLoading: false,
setSignedIn: () => { }
setSignedIn: () => { },
forceScheduleRevalidation: () => { }
});

export default SessionContext
3 changes: 2 additions & 1 deletion src/hooks/useSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const useSession = () => {
}
}

const { data, isLoading } = useSwr("auth/info/", trySession, {
const { data, isLoading, mutate } = useSwr("auth/info/", trySession, {
focusThrottleInterval: 1800000
});

Expand All @@ -26,6 +26,7 @@ const useSession = () => {
return {
signedIn: data ? data.signed : false,
user: data ? data : null,
forceScheduleRevalidation: mutate,
isLoading
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useStudentCourseUnits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ export default () => {
error,
loading: !data,
isValidating,
mutate,
forceCourseUnitsRevalidation: mutate,
};
};
14 changes: 11 additions & 3 deletions src/pages/Exchange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,16 @@ const ExchangePage = () => {
const { schedule, loading: loadingSchedule , sigarraSynced} = useSchedule();
const [originalExchangeSchedule, setOriginalExchangeSchedule] = useState<Array<ClassDescriptor>>([]);
const [exchangeSchedule, setExchangeSchedule] = useState<Array<ClassDescriptor>>([]);
const { signedIn, user } = useContext(SessionContext);
const { enrolledCourseUnits } = useStudentCourseUnits();
const { signedIn, user, forceScheduleRevalidation, isSessionLoading } = useContext(SessionContext);
const { enrolledCourseUnits, forceCourseUnitsRevalidation } = useStudentCourseUnits();

useEffect(() => {
forceScheduleRevalidation();
}, [schedule])

useEffect(() => {
if(user?.eligible_exchange) forceCourseUnitsRevalidation();
}, [user])

useEffect(() => {
if (creatingRequest) setSidebarStatus(ExchangeSidebarStatus.CREATING_REQUEST)
Expand Down Expand Up @@ -112,7 +120,7 @@ const ExchangePage = () => {
<TabsTrigger value="enrollments">Inscrições</TabsTrigger>
</TabsList>
<TabsContent value="requests">
{user?.eligible_exchange
{!isSessionLoading && user?.eligible_exchange
? <ExchangeSidebarStatusView
sidebarStatus={sidebarStatus}
setExchangeSidebarStatus={setSidebarStatus}
Expand Down
16 changes: 13 additions & 3 deletions src/utils/mail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@ export const mailtoStringBuilder = (nmec: string | Array<string>) => {
if (Array.isArray(nmec)) {
let mailto = "mailto:"
nmec.forEach(nmec => {
mailto += `up${nmec}@up.pt,`
mailto += `up${nmec}@up.pt;`
})

return mailto;
return mailto.slice(0, -1);
}

return `mailto:up${nmec}@up.pt`
}

export const listEmailExchanges = (items: Array<{
participant_nmec: string,
goes_from: string,
goes_to: string,
course_acronym: string
}>) => {
return items.map(item => `De ${item.goes_from} para ${item.goes_to} no curso ${item.course_acronym}.`).join("%0D%0A")
return items.map(item => `${item.participant_nmec} pediu para trocar de ${item.goes_from} para ${item.goes_to} no curso ${item.course_acronym}.`).join("%0D%0A")
}

export const listEmailEnrollments = (items: Array<{
participant_nmec: string,
goes_to: string,
course: number,
course_unit_id: number
}>) => {
return items.map(item => `${item.participant_nmec} pediu para ir para ${item.goes_to} (${item.course_unit_id}) no curso ${item.course}.`).join("%0D%0A")
}

0 comments on commit 450a263

Please sign in to comment.