[resumes][feat] migrate to use location db and role enum (#506)

* [resumes][feat] use role and countries typeaheads

* [resumes][feat] add location and role typeaheads

* [resumes][chore] locationId migration

* [resumes][fix] update upsert to take in locationId

* [resumes][refactor] use typeahead for browse filters

* [resumes][feat] use role and countries typeaheads

* [resumes][chore] locationId migration

* [resumes][feat] fetch location on resumes page

* [resumes][feat] enable edit resume form

* [resumes][misc] update namings and oredrings

* [resumes][feat] add default locations

* [resumes][fix] truncate title text in resume card

* [resumes][fix] filter out selected options

* [resumes][feat] add more countries to default search

* [resumes][feat] update default roles

* [resumes][chore] revert removal of value

* [resumes]feat] add default location for migration file

* [resumes][fix] fix merge conflicts

Co-authored-by: Wu Peirong <wupeirong294@gmail.com>
This commit is contained in:
Keane Chan
2022-11-05 21:56:46 +08:00
committed by GitHub
parent 9815d125ff
commit 1ebd32ca2f
14 changed files with 605 additions and 393 deletions

View File

@@ -1,8 +1,6 @@
import { z } from 'zod';
import { Vote } from '@prisma/client';
import { EXPERIENCES, LOCATIONS, ROLES } from '~/utils/resumes/resumeFilters';
import { createRouter } from '../context';
import type { Resume } from '~/types/resume';
@@ -35,7 +33,7 @@ export const resumesRouter = createRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
@@ -49,6 +47,11 @@ export const resumesRouter = createRouter()
},
},
comments: true,
location: {
select: {
name: true,
},
},
stars: {
where: {
OR: {
@@ -79,7 +82,7 @@ export const resumesRouter = createRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
@@ -92,7 +95,8 @@ export const resumesRouter = createRouter()
id: r.id,
isResolved: r.isResolved,
isStarredByUser: r.stars.length > 0,
location: r.location,
location: r.location.name,
locationId: r.locationId,
numComments: r._count.comments,
numStars: r._count.stars,
role: r.role,
@@ -103,7 +107,7 @@ export const resumesRouter = createRouter()
return resume;
});
// Group by role and count, taking into account all role/experience/location/isUnreviewed filters and search value
// Group by role and count, taking into account all role/experience/locationId/isUnreviewed filters and search value
const roleCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
@@ -112,7 +116,7 @@ export const resumesRouter = createRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
});
@@ -122,20 +126,6 @@ export const resumesRouter = createRouter()
roleCounts.map((rc) => [rc.role, rc._count._all]),
);
// Filter out roles with zero counts and map to object where key = role and value = 0
const zeroRoleCounts = Object.fromEntries(
ROLES.filter((r) => !(r.value in mappedRoleCounts)).map((r) => [
r.value,
0,
]),
);
// Combine to form singular role counts object
const processedRoleCounts = {
...mappedRoleCounts,
...zeroRoleCounts,
};
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
@@ -143,7 +133,7 @@ export const resumesRouter = createRouter()
by: ['experience'],
where: {
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
@@ -151,21 +141,12 @@ export const resumesRouter = createRouter()
const mappedExperienceCounts = Object.fromEntries(
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
);
const zeroExperienceCounts = Object.fromEntries(
EXPERIENCES.filter((e) => !(e.value in mappedExperienceCounts)).map(
(e) => [e.value, 0],
),
);
const processedExperienceCounts = {
...mappedExperienceCounts,
...zeroExperienceCounts,
};
const locationCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
},
by: ['location'],
by: ['locationId'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
@@ -174,23 +155,13 @@ export const resumesRouter = createRouter()
},
});
const mappedLocationCounts = Object.fromEntries(
locationCounts.map((lc) => [lc.location, lc._count._all]),
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
);
const zeroLocationCounts = Object.fromEntries(
LOCATIONS.filter((l) => !(l.value in mappedLocationCounts)).map((l) => [
l.value,
0,
]),
);
const processedLocationCounts = {
...mappedLocationCounts,
...zeroLocationCounts,
};
const filterCounts = {
Experience: processedExperienceCounts,
Location: processedLocationCounts,
Role: processedRoleCounts,
experience: mappedExperienceCounts,
location: mappedLocationCounts,
role: mappedRoleCounts,
};
return {
@@ -217,6 +188,11 @@ export const resumesRouter = createRouter()
stars: true,
},
},
location: {
select: {
name: true,
},
},
stars: {
where: {
OR: {

View File

@@ -1,19 +1,16 @@
import { z } from 'zod';
import { EXPERIENCES, LOCATIONS, ROLES } from '~/utils/resumes/resumeFilters';
import { createProtectedRouter } from '../context';
import type { Resume } from '~/types/resume';
export const resumesResumeUserRouter = createProtectedRouter()
.mutation('upsert', {
// TODO: Use enums for experience, location, role
input: z.object({
additionalInfo: z.string().optional(),
experience: z.string(),
id: z.string().optional(),
location: z.string(),
locationId: z.string(),
role: z.string(),
title: z.string(),
url: z.string(),
@@ -25,7 +22,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
create: {
additionalInfo: input.additionalInfo,
experience: input.experience,
location: input.location,
locationId: input.locationId,
role: input.role,
title: input.title,
url: input.url,
@@ -34,7 +31,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
update: {
additionalInfo: input.additionalInfo,
experience: input.experience,
location: input.location,
locationId: input.locationId,
role: input.role,
title: input.title,
url: input.url,
@@ -91,7 +88,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
resume: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
@@ -108,6 +105,11 @@ export const resumesResumeUserRouter = createProtectedRouter()
stars: true,
},
},
location: {
select: {
name: true,
},
},
user: {
select: {
name: true,
@@ -144,7 +146,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
resume: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
@@ -160,7 +162,8 @@ export const resumesResumeUserRouter = createProtectedRouter()
id: rs.resume.id,
isResolved: rs.resume.isResolved,
isStarredByUser: true,
location: rs.resume.location,
location: rs.resume.location.name,
locationId: rs.resume.locationId,
numComments: rs.resume._count.comments,
numStars: rs.resume._count.stars,
role: rs.resume.role,
@@ -179,7 +182,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
stars: {
some: {
userId,
@@ -191,16 +194,6 @@ export const resumesResumeUserRouter = createProtectedRouter()
const mappedRoleCounts = Object.fromEntries(
roleCounts.map((rc) => [rc.role, rc._count._all]),
);
const zeroRoleCounts = Object.fromEntries(
ROLES.filter((r) => !(r.value in mappedRoleCounts)).map((r) => [
r.value,
0,
]),
);
const processedRoleCounts = {
...mappedRoleCounts,
...zeroRoleCounts,
};
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
@@ -209,7 +202,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
by: ['experience'],
where: {
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
stars: {
some: {
@@ -222,21 +215,12 @@ export const resumesResumeUserRouter = createProtectedRouter()
const mappedExperienceCounts = Object.fromEntries(
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
);
const zeroExperienceCounts = Object.fromEntries(
EXPERIENCES.filter((e) => !(e.value in mappedExperienceCounts)).map(
(e) => [e.value, 0],
),
);
const processedExperienceCounts = {
...mappedExperienceCounts,
...zeroExperienceCounts,
};
const locationCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
},
by: ['location'],
by: ['locationId'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
@@ -250,23 +234,13 @@ export const resumesResumeUserRouter = createProtectedRouter()
},
});
const mappedLocationCounts = Object.fromEntries(
locationCounts.map((lc) => [lc.location, lc._count._all]),
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
);
const zeroLocationCounts = Object.fromEntries(
LOCATIONS.filter((l) => !(l.value in mappedLocationCounts)).map((l) => [
l.value,
0,
]),
);
const processedLocationCounts = {
...mappedLocationCounts,
...zeroLocationCounts,
};
const filterCounts = {
Experience: processedExperienceCounts,
Location: processedLocationCounts,
Role: processedRoleCounts,
experience: mappedExperienceCounts,
location: mappedLocationCounts,
role: mappedRoleCounts,
};
return { filterCounts, mappedResumeData, totalRecords };
@@ -299,7 +273,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
@@ -313,6 +287,11 @@ export const resumesResumeUserRouter = createProtectedRouter()
stars: true,
},
},
location: {
select: {
name: true,
},
},
stars: {
where: {
userId,
@@ -341,7 +320,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
@@ -355,7 +334,8 @@ export const resumesResumeUserRouter = createProtectedRouter()
id: r.id,
isResolved: r.isResolved,
isStarredByUser: r.stars.length > 0,
location: r.location,
location: r.location.name,
locationId: r.locationId,
numComments: r._count.comments,
numStars: r._count.stars,
role: r.role,
@@ -374,7 +354,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
},
@@ -382,16 +362,6 @@ export const resumesResumeUserRouter = createProtectedRouter()
const mappedRoleCounts = Object.fromEntries(
roleCounts.map((rc) => [rc.role, rc._count._all]),
);
const zeroRoleCounts = Object.fromEntries(
ROLES.filter((r) => !(r.value in mappedRoleCounts)).map((r) => [
r.value,
0,
]),
);
const processedRoleCounts = {
...mappedRoleCounts,
...zeroRoleCounts,
};
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
@@ -400,7 +370,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
by: ['experience'],
where: {
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
locationId: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
@@ -409,21 +379,12 @@ export const resumesResumeUserRouter = createProtectedRouter()
const mappedExperienceCounts = Object.fromEntries(
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
);
const zeroExperienceCounts = Object.fromEntries(
EXPERIENCES.filter((e) => !(e.value in mappedExperienceCounts)).map(
(e) => [e.value, 0],
),
);
const processedExperienceCounts = {
...mappedExperienceCounts,
...zeroExperienceCounts,
};
const locationCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
},
by: ['location'],
by: ['locationId'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
@@ -433,23 +394,13 @@ export const resumesResumeUserRouter = createProtectedRouter()
},
});
const mappedLocationCounts = Object.fromEntries(
locationCounts.map((lc) => [lc.location, lc._count._all]),
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
);
const zeroLocationCounts = Object.fromEntries(
LOCATIONS.filter((l) => !(l.value in mappedLocationCounts)).map((l) => [
l.value,
0,
]),
);
const processedLocationCounts = {
...mappedLocationCounts,
...zeroLocationCounts,
};
const filterCounts = {
Experience: processedExperienceCounts,
Location: processedLocationCounts,
Role: processedRoleCounts,
experience: mappedExperienceCounts,
location: mappedLocationCounts,
role: mappedRoleCounts,
};
return { filterCounts, mappedResumeData, totalRecords };