[resumes][fix] add resolve resume functionality (#442)

* [resumes][fix] button getting cut off

* [resumes][feat] add resolve functionality

* [resumes][feat] replace student roles with internship

* [resumes][feat] fetch isResolved field
pull/444/head
Keane Chan 2 years ago committed by GitHub
parent e3620faafe
commit 410d8712c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "ResumesResume" ADD COLUMN "isResolved" BOOLEAN NOT NULL DEFAULT false;

@ -120,6 +120,7 @@ model ResumesResume {
location String @db.Text
url String
additionalInfo String? @db.Text
isResolved Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@ -9,6 +9,7 @@ import {
AcademicCapIcon,
BriefcaseIcon,
CalendarIcon,
CheckCircleIcon,
InformationCircleIcon,
MapPinIcon,
PencilSquareIcon,
@ -57,24 +58,33 @@ export default function ResumeReviewPage() {
);
const starMutation = trpc.useMutation('resumes.resume.star', {
onSuccess() {
utils.invalidateQueries(['resumes.resume.findOne']);
utils.invalidateQueries(['resumes.resume.findAll']);
utils.invalidateQueries(['resumes.resume.user.findUserStarred']);
utils.invalidateQueries(['resumes.resume.user.findUserCreated']);
invalidateResumeQueries();
},
});
const unstarMutation = trpc.useMutation('resumes.resume.unstar', {
onSuccess() {
utils.invalidateQueries(['resumes.resume.findOne']);
utils.invalidateQueries(['resumes.resume.findAll']);
utils.invalidateQueries(['resumes.resume.user.findUserStarred']);
utils.invalidateQueries(['resumes.resume.user.findUserCreated']);
invalidateResumeQueries();
},
});
const resolveMutation = trpc.useMutation('resumes.resume.user.resolve', {
onSuccess() {
invalidateResumeQueries();
},
});
const invalidateResumeQueries = () => {
utils.invalidateQueries(['resumes.resume.findOne']);
utils.invalidateQueries(['resumes.resume.findAll']);
utils.invalidateQueries(['resumes.resume.user.findUserStarred']);
utils.invalidateQueries(['resumes.resume.user.findUserCreated']);
};
const userIsOwner =
session?.user?.id !== undefined &&
session.user.id === detailsQuery.data?.userId;
const isResumeResolved = detailsQuery.data?.isResolved;
const [isEditMode, setIsEditMode] = useState(false);
const [showCommentsForm, setShowCommentsForm] = useState(false);
@ -139,6 +149,13 @@ export default function ResumeReviewPage() {
setIsEditMode(true);
};
const onResolveButtonClick = () => {
resolveMutation.mutate({
id: resumeId as string,
val: !isResumeResolved,
});
};
const renderReviewButton = () => {
if (session === null) {
return (
@ -175,10 +192,7 @@ export default function ResumeReviewPage() {
url: detailsQuery.data.url,
}}
onClose={() => {
utils.invalidateQueries(['resumes.resume.findOne']);
utils.invalidateQueries(['resumes.resume.findAll']);
utils.invalidateQueries(['resumes.resume.user.findUserStarred']);
utils.invalidateQueries(['resumes.resume.user.findUserCreated']);
invalidateResumeQueries();
setIsEditMode(false);
}}
/>
@ -206,17 +220,36 @@ export default function ResumeReviewPage() {
</h1>
<div className="flex gap-3 xl:pr-4">
{userIsOwner && (
<Button
addonPosition="start"
className="h-10 shadow-md"
icon={PencilSquareIcon}
label="Edit"
variant="tertiary"
onClick={onEditButtonClick}
/>
<>
<Button
addonPosition="start"
className="h-10 shadow-md"
icon={PencilSquareIcon}
label="Edit"
variant="tertiary"
onClick={onEditButtonClick}
/>
<button
className="isolate inline-flex h-10 items-center space-x-4 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-md hover:bg-slate-50 focus:ring-slate-600 disabled:hover:bg-white"
disabled={resolveMutation.isLoading}
type="button"
onClick={onResolveButtonClick}>
<div className="-ml-1 mr-2 h-5 w-5">
{resolveMutation.isLoading ? (
<Spinner className="mt-0.5" size="xs" />
) : (
<CheckCircleIcon
aria-hidden="true"
className={isResumeResolved ? '' : 'text-slate-400'}
/>
)}
</div>
{isResumeResolved ? 'Resolved' : 'Resolve'}
</button>
</>
)}
<button
className="isolate inline-flex h-10 items-center space-x-4 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-md hover:bg-slate-50 disabled:hover:bg-white"
className="isolate inline-flex h-10 items-center space-x-4 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-md hover:bg-slate-50 focus:ring-slate-600 disabled:hover:bg-white"
disabled={starMutation.isLoading || unstarMutation.isLoading}
type="button"
onClick={onStarButtonClick}>

@ -542,7 +542,7 @@ export default function ResumeHomePage() {
/>
</div>
<Button
className="lg:hidden"
className="whitespace-pre-wrap px-2 lg:hidden"
label="Submit Resume"
variant="primary"
onClick={onSubmitResume}

@ -96,6 +96,7 @@ export const resumesRouter = createRouter()
createdAt: r.createdAt,
experience: r.experience,
id: r.id,
isResolved: r.isResolved,
isStarredByUser: r.stars.length > 0,
location: r.location,
numComments: r._count.comments,

@ -44,6 +44,23 @@ export const resumesResumeUserRouter = createProtectedRouter()
});
},
})
.mutation('resolve', {
input: z.object({
id: z.string(),
val: z.boolean(),
}),
async resolve({ ctx, input }) {
const resume = await ctx.prisma.resumesResume.update({
data: {
isResolved: input.val,
},
where: {
id: input.id,
},
});
return resume.isResolved;
},
})
.query('findUserStarred', {
input: z.object({
experienceFilters: z.string().array(),
@ -147,6 +164,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
createdAt: rs.resume.createdAt,
experience: rs.resume.experience,
id: rs.resume.id,
isResolved: rs.resume.isResolved,
isStarredByUser: true,
location: rs.resume.location,
numComments: rs.resume._count.comments,
@ -250,6 +268,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
createdAt: r.createdAt,
experience: r.experience,
id: r.id,
isResolved: r.isResolved,
isStarredByUser: r.stars.length > 0,
location: r.location,
numComments: r._count.comments,

@ -3,6 +3,7 @@ export type Resume = {
createdAt: Date;
experience: string;
id: string;
isResolved: boolean;
isStarredByUser: boolean;
location: string;
numComments: number;

@ -14,12 +14,9 @@ export type RoleFilter =
export type ExperienceFilter =
| 'Entry Level (0 - 2 years)'
| 'Freshman'
| 'Junior'
| 'Internship'
| 'Mid Level (3 - 5 years)'
| 'Senior Level (5+ years)'
| 'Senior'
| 'Sophomore';
| 'Senior Level (5+ years)';
export type LocationFilter = 'India' | 'Singapore' | 'United States';
@ -79,10 +76,7 @@ export const ROLES: Array<FilterOption<RoleFilter>> = [
];
export const EXPERIENCES: Array<FilterOption<ExperienceFilter>> = [
{ label: 'Freshman', value: 'Freshman' },
{ label: 'Sophomore', value: 'Sophomore' },
{ label: 'Junior', value: 'Junior' },
{ label: 'Senior', value: 'Senior' },
{ label: 'Internship', value: 'Internship' },
{
label: 'Entry Level (0 - 2 years)',
value: 'Entry Level (0 - 2 years)',
@ -133,7 +127,7 @@ export const SHORTCUTS: Array<Shortcut> = [
},
{
filters: INITIAL_FILTER_STATE,
name: 'GOATs',
name: 'Top 10',
sortOrder: 'popular',
},
{

Loading…
Cancel
Save