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

feat: hover tooltip to show rejection reason for referrals πŸ‘€βŒπŸ’¬ #542

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
31 changes: 29 additions & 2 deletions apps/member-profile/app/routes/_profile.profile.referrals.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { Link, Outlet, useLoaderData } from '@remix-run/react';
import { Send } from 'react-feather';
import { Info, Send } from 'react-feather';
import { match } from 'ts-pattern';

import { listReferrals } from '@oyster/core/referrals';
import { type ReferralStatus } from '@oyster/core/referrals/ui';
import { Button, getButtonCn, Pill, Text } from '@oyster/ui';
import {
Tooltip,
TooltipContent,
TooltipText,
TooltipTrigger,
} from '@oyster/ui/tooltip';

import {
EmptyState,
Expand All @@ -19,6 +25,7 @@ import {
} from '@/shared/components/profile';
import { Route } from '@/shared/constants';
import { ensureUserAuthenticated, user } from '@/shared/session.server';
import { formatRejectionReason } from '@/shared/utils/format.utils';

export async function loader({ request }: LoaderFunctionArgs) {
const session = await ensureUserAuthenticated(request);
Expand All @@ -30,6 +37,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
'referrals.id',
'referrals.lastName',
'referrals.status',
'applications.rejectionReason',
],
where: { referrerId: user(session) },
});
Expand Down Expand Up @@ -86,7 +94,26 @@ export default function Referrals() {
return <Pill color="orange-100">Applied</Pill>;
})
.with('rejected', () => {
return <Pill color="red-100">Rejected</Pill>;
return referral.rejectionReason ? (
<Tooltip>
<TooltipTrigger>
<div className="group flex items-center gap-0.5">
<Pill color="red-100">Rejected</Pill>
<Info
size={14}
className="text-red-500 transition-colors duration-300 group-hover:text-gray-600"
/>
</div>
</TooltipTrigger>
<TooltipContent>
<TooltipText>
{formatRejectionReason(referral.rejectionReason)}
</TooltipText>
</TooltipContent>
</Tooltip>
) : (
<Pill color="red-100">Rejected</Pill>
);
})
.with('sent', () => {
return <Pill color="amber-100">Sent</Pill>;
Expand Down
32 changes: 32 additions & 0 deletions apps/member-profile/app/shared/utils/format.utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ApplicationRejectionReason } from '@/modules/application/application.types';

export function formatHeadline({
graduationYear,
headline,
Expand Down Expand Up @@ -25,3 +27,33 @@ export function formatName({
? `${firstName} (${preferredName}) ${lastName}`
: `${firstName} ${lastName}`;
}

/**
* Formats a rejection reason into a user-friendly message.
*
* @param {string} reason - The raw rejection reason.
* @returns {string} A formatted, user-friendly explanation of the rejection reason.
*
* @example
* // Returns "This referral was rejected because an ineligible major."
* formatRejectionReason('ineligible_major');
*
**/
export function formatRejectionReason(reason: string) {
if (!reason) return 'Something happened.';
wflore19 marked this conversation as resolved.
Show resolved Hide resolved

switch (reason) {
case ApplicationRejectionReason.BAD_LINKEDIN:
return 'Incorrect or suspicious LinkedIn';
wflore19 marked this conversation as resolved.
Show resolved Hide resolved
case ApplicationRejectionReason.IS_INTERNATIONAL:
return 'Not enrolled in US or Canada';
case ApplicationRejectionReason.INELIGIBLE_MAJOR:
return 'Not the right major';
case ApplicationRejectionReason.NOT_UNDERGRADUATE:
return 'Not an undergrad student';
case ApplicationRejectionReason.OTHER:
return 'Other reason';
default:
return reason || 'Other Reason';
}
}
3 changes: 2 additions & 1 deletion packages/core/src/modules/referral/referral.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ type ListReferralsOptions<Selection> = {
};

export async function listReferrals<
Selection extends SelectExpression<DB, 'referrals'>,
Selection extends SelectExpression<DB, 'referrals' | 'applications'>,
>({ select, where }: ListReferralsOptions<Selection>) {
const referrals = await db
.selectFrom('referrals')
.innerJoin('applications', 'applications.referralId', 'referrals.id')
.select(select)
.$if(!!where.referrerId, (qb) => {
return qb.where('referrerId', '=', where.referrerId as string);
Expand Down