Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor/status values #583

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/site/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
"plugin:@typescript-eslint/recommended",
"next/core-web-vitals"
],
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"eqeqeq": "error",
"no-unused-expressions": "warn",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/switch-exhaustiveness-check": "error",
"react/button-has-type": "error",
"react/no-danger": "warn",
"react/no-unstable-nested-components": "error",
Expand Down
33 changes: 9 additions & 24 deletions apps/site/src/app/(main)/portal/@applicant/ApplicantPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { redirect } from "next/navigation";

import useUserIdentity from "@/lib/utils/useUserIdentity";
import { Status } from "@/lib/userRecord";

import ConfirmAttendance from "./components/ConfirmAttendance";
import Message from "./components/Message";
Expand All @@ -11,20 +12,6 @@ import ReturnHome from "./components/ReturnHome";
import VerticalTimeline from "./components/timeline/VerticalTimeline";
import BackgroundStars from "./components/BackgroundStars";

// TODO: use common Status enum from userRecord.ts

export const enum PortalStatus {
pending = "PENDING_REVIEW",
reviewed = "REVIEWED",
accepted = "ACCEPTED",
rejected = "REJECTED",
waitlisted = "WAITLISTED",
waived = "WAIVER_SIGNED",
confirmed = "CONFIRMED",
attending = "ATTENDING",
void = "VOID",
}

const rolesArray = ["Mentor", "Hacker", "Volunteer"];

function Portal() {
Expand All @@ -45,12 +32,12 @@ function Portal() {
);

const submittedWaiver =
status === PortalStatus.waived ||
status === PortalStatus.confirmed ||
status === PortalStatus.attending;
status === Status.Signed ||
status === Status.Confirmed ||
status === Status.Attending;

const needsToSignWaiver = status === PortalStatus.accepted;
const rejected = status === PortalStatus.rejected;
const needsToSignWaiver = status === Status.Accepted;
const rejected = status === Status.Rejected;

return (
<div className="relative">
Expand All @@ -59,12 +46,10 @@ function Portal() {
<h2 className="font-bold font-display text-[var(--color-white)] mb-4 md:mb-[42px] text-[15px] sm:text-2xl md:text-[40px] md:leading-10">
{roleToDisplay} Application Status
</h2>
<VerticalTimeline status={status as PortalStatus} />
<Message status={status as PortalStatus} />
<VerticalTimeline status={status as Status} />
<Message status={status as Status} />
{needsToSignWaiver && <SignWaiver />}
{submittedWaiver && (
<ConfirmAttendance status={status as PortalStatus} />
)}
{submittedWaiver && <ConfirmAttendance status={status as Status} />}
{rejected && <ReturnHome />}
</div>
<BackgroundStars className="right-[-15%] bottom-[21%]" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { PortalStatus } from "../ApplicantPortal";
import { Status } from "@/lib/userRecord";
import RsvpForm from "./RsvpForm";

interface ConfirmAttendanceProps {
status: PortalStatus;
status: Status;
}

function ConfirmAttendance({ status }: ConfirmAttendanceProps) {
const buttonText =
status === PortalStatus.confirmed || status === PortalStatus.attending
status === Status.Confirmed || status === Status.Attending
? "I am no longer able to attend IrvineHacks 2025"
: "I will be attending IrvineHacks 2025";

Expand All @@ -16,15 +16,14 @@ function ConfirmAttendance({ status }: ConfirmAttendanceProps) {
<h3 className="font-bold font-display mb-[9px] md:mb-[20px] text-[0.9375rem] sm:text-2xl md:text-[2.5rem] md:leading-10">
RSVP
</h3>
{status === PortalStatus.confirmed ||
status === PortalStatus.attending ? (
{status === Status.Confirmed || status === Status.Attending ? (
<>
<p className="text-xs sm:text-base md:text-2xl">
Thank you for confirming your attendance! We look forward to seeing
you at IrvineHacks! If you are no longer able to attend, please let
us know using the button below.
</p>
{status === PortalStatus.attending && (
{status === Status.Attending && (
<strong className="text-red-600 text-xs sm:text-base md:text-xl mb-3 w-full text-center inline-block">
WARNING: After clicking the button below, you will{" "}
<span className="underline">NOT</span> be able to RSVP again.
Expand All @@ -40,7 +39,7 @@ function ConfirmAttendance({ status }: ConfirmAttendanceProps) {
<div className="mt-2 md:mt-8">
<RsvpForm
buttonText={buttonText}
showWarning={status === PortalStatus.attending}
showWarning={status === Status.Attending}
/>
</div>
</div>
Expand Down
106 changes: 65 additions & 41 deletions apps/site/src/app/(main)/portal/@applicant/components/Message.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,77 @@
import { PortalStatus } from "../ApplicantPortal";
import { Status } from "@/lib/userRecord";

interface MessageProps {
status: PortalStatus;
status: Status;
}

function Message({ status }: MessageProps) {
const submittedMessage = (
<p>
Thank you for submitting your application! We are currently reviewing
applications on a rolling basis, and you will hear back from us soon!
</p>
);
let message: JSX.Element;

switch (status) {
case Status.Pending:
case Status.Reviewed: {
message = (
<p>
Thank you for submitting your application! We are currently reviewing
applications on a rolling basis, and you will hear back from us soon!
</p>
);
break;
}

case Status.Rejected: {
message = (
<p className="mt-4">
Thank you for applying to IrvineHacks this year. We have read through
many applications so far, and unfortunately are unable to offer you a
spot at our event. We highly encourage you to continue developing your
skills and passion for technology. We would love to see you apply
again next year!
</p>
);
break;
}

case Status.Waitlisted: {
message = (
<p className="mt-4">
Thank you for applying to IrvineHacks this year. We have read through
many applications so far, and are able to offer you a spot on the
event waitlist. Please check your email for more info about the
waitlist and waitlist walk-ins!
</p>
);
break;
}

case Status.Accepted:
case Status.Signed:
case Status.Confirmed:
case Status.Attending: {
message = <></>;
break;
}

case Status.Void: {
message = (
<p className="mt-4">
Unfortunately, you are not able to RSVP for IrvineHacks at this time
and will not be able to come to the event. However, we would love to
see you apply again next year!
</p>
);
break;
}

const messages: Record<PortalStatus, JSX.Element> = {
[PortalStatus.pending]: submittedMessage,
[PortalStatus.reviewed]: submittedMessage,
[PortalStatus.rejected]: (
<p className="mt-4">
Thank you for applying to IrvineHacks this year. We have read through
many applications so far, and unfortunately are unable to offer you a
spot at our event. We highly encourage you to continue developing your
skills and passion for technology. We would love to see you apply again
next year!
</p>
),
[PortalStatus.waitlisted]: (
<p className="mt-4">
Thank you for applying to IrvineHacks this year. We have read through
many applications so far, and are able to offer you a spot on the event
waitlist. Please check your email for more info about the waitlist and
waitlist walk-ins!
</p>
),
[PortalStatus.accepted]: <></>,
[PortalStatus.waived]: <></>,
[PortalStatus.confirmed]: <></>,
[PortalStatus.attending]: <></>,
[PortalStatus.void]: (
<p className="mt-4">
Unfortunately, you are not able to RSVP for IrvineHacks at this time and
will not be able to come to the event. However, we would love to see you
apply again next year!
</p>
),
};
default: {
const exhaustiveCheck: never = status;
throw new Error(`Unhandled status: ${exhaustiveCheck}`);
}
}

return (
<div className="font-body text-[var(--color-white)] text-xs sm:text-base md:text-2xl">
{messages[status]}
{message}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { TimelineComponent } from "./TimelineComponent";
import { PortalStatus } from "../.././ApplicantPortal";
import { Status } from "@/lib/userRecord";
import { StatusImageProps } from "./StatusImage";

export const RSVPComponent = ({ status }: { status: PortalStatus }) => {
export const RSVPComponent = ({ status }: { status: Status }) => {
let verdict = null;

if (status === PortalStatus.accepted || status === PortalStatus.waived) {
if (status === Status.Accepted || status === Status.Signed) {
verdict = {
text: "Confirm Attendance",
finished: false,
statusIcon: "Pending",
};
} else if (
status === PortalStatus.confirmed ||
status === PortalStatus.attending
) {
} else if (status === Status.Confirmed || status === Status.Attending) {
verdict = {
text: "Attendance Confirmed",
finished: true,
statusIcon: "Accepted",
};
} else if (status === PortalStatus.void) {
} else if (status === Status.Void) {
verdict = {
text: "No RSVP Indicated",
finished: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,67 @@
import { TimelineComponent } from "./TimelineComponent";
import { PortalStatus } from "../.././ApplicantPortal";
import { Status } from "@/lib/userRecord";
import { StatusImageProps } from "./StatusImage";

export const VerdictComponent = ({ status }: { status: PortalStatus }) => {
let verdict = null;
export const VerdictComponent = ({ status }: { status: Status }) => {
let verdict: {
text: string;
finished: boolean;
statusIcon: StatusImageProps["statusIcon"];
} | null = null;

if (
status === PortalStatus.accepted ||
status === PortalStatus.void ||
status === PortalStatus.waived ||
status === PortalStatus.confirmed ||
status === PortalStatus.attending
) {
verdict = {
text: "Application Accepted",
finished: true,
statusIcon: "Accepted",
};
} else if (status === PortalStatus.rejected) {
verdict = {
text: "Application Rejected",
finished: true,
statusIcon: "Rejected",
};
} else if (status === PortalStatus.waitlisted) {
verdict = {
text: "Application Waitlisted",
finished: true,
statusIcon: "Pending",
};
} else if (
status === PortalStatus.pending ||
status === PortalStatus.reviewed
) {
verdict = {
text: "Application Under Review",
finished: true,
statusIcon: "Pending",
};
switch (status) {
case Status.Accepted:
case Status.Void:
case Status.Signed:
case Status.Confirmed:
case Status.Attending: {
verdict = {
text: "Application Accepted",
finished: true,
statusIcon: "Accepted",
};
break;
}

case Status.Rejected: {
verdict = {
text: "Application Rejected",
finished: true,
statusIcon: "Rejected",
};
break;
}

case Status.Waitlisted: {
verdict = {
text: "Application Waitlisted",
finished: true,
statusIcon: "Pending",
};
break;
}

case Status.Pending:
case Status.Reviewed: {
verdict = {
text: "Application Under Review",
finished: true,
statusIcon: "Pending",
};
break;
}

default: {
const exhaustiveCheck: never = status;
throw new Error(`Unhandled status: ${exhaustiveCheck}`);
}
}

return verdict ? (
<TimelineComponent
text={verdict.text}
finished={verdict.finished}
statusIcon={verdict.statusIcon as StatusImageProps["statusIcon"]}
statusIcon={verdict.statusIcon}
/>
) : null;
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from "react";
import { PortalStatus } from "../../ApplicantPortal";
import { Status } from "@/lib/userRecord";
import { SubmissionComponent } from "./SubmissionComponent";
import { VerdictComponent } from "./VerdictComponent";
import { WaiverComponent } from "./WaiverComponent";
import { RSVPComponent } from "./RSVPComponent";

interface VerticalTimelineProps {
status: PortalStatus;
status: Status;
}

function VerticalTimeline({ status }: VerticalTimelineProps) {
Expand Down
Loading
Loading