[resumes][feat] Add dynamic filters and unreviewed shortcut (#455)

This commit is contained in:
Su Yin
2022-10-29 17:27:05 +08:00
committed by GitHub
parent b1f16a06e9
commit 8dfe6b0bdd
4 changed files with 337 additions and 64 deletions

View File

@@ -11,8 +11,8 @@ export const resumesRouter = createRouter()
.query('findAll', {
input: z.object({
experienceFilters: z.string().array(),
isUnreviewed: z.boolean(),
locationFilters: z.string().array(),
numComments: z.number().optional(),
roleFilters: z.string().array(),
searchValue: z.string(),
skip: z.number(),
@@ -25,7 +25,7 @@ export const resumesRouter = createRouter()
locationFilters,
experienceFilters,
sortOrder,
numComments,
isUnreviewed,
skip,
searchValue,
take,
@@ -33,12 +33,8 @@ export const resumesRouter = createRouter()
const userId = ctx.session?.user?.id;
const totalRecords = await ctx.prisma.resumesResume.count({
where: {
...(numComments === 0 && {
comments: {
none: {},
},
}),
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
@@ -81,12 +77,8 @@ export const resumesRouter = createRouter()
skip,
take,
where: {
...(numComments === 0 && {
comments: {
none: {},
},
}),
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
@@ -110,7 +102,105 @@ export const resumesRouter = createRouter()
};
return resume;
});
return { mappedResumeData, totalRecords };
// Group by role and count, taking into account all role/experience/location/isUnreviewed filters and search value
const roleCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
},
by: ['role'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
});
// Map all nonzero counts from array to object where key = role and value = count
const mappedRoleCounts = Object.fromEntries(
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,
},
by: ['experience'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
});
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'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
},
});
const mappedLocationCounts = Object.fromEntries(
locationCounts.map((lc) => [lc.location, 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,
};
return {
filterCounts,
mappedResumeData,
totalRecords,
};
},
})
.query('findOne', {

View File

@@ -1,5 +1,7 @@
import { z } from 'zod';
import { EXPERIENCES, LOCATIONS, ROLES } from '~/utils/resumes/resumeFilters';
import { createProtectedRouter } from '../context';
import type { Resume } from '~/types/resume';
@@ -64,8 +66,8 @@ export const resumesResumeUserRouter = createProtectedRouter()
.query('findUserStarred', {
input: z.object({
experienceFilters: z.string().array(),
isUnreviewed: z.boolean(),
locationFilters: z.string().array(),
numComments: z.number().optional(),
roleFilters: z.string().array(),
searchValue: z.string(),
skip: z.number(),
@@ -80,19 +82,15 @@ export const resumesResumeUserRouter = createProtectedRouter()
experienceFilters,
searchValue,
sortOrder,
numComments,
isUnreviewed,
skip,
take,
} = input;
const totalRecords = await ctx.prisma.resumesStar.count({
where: {
resume: {
...(numComments === 0 && {
comments: {
none: {},
},
}),
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
@@ -144,12 +142,8 @@ export const resumesResumeUserRouter = createProtectedRouter()
take,
where: {
resume: {
...(numComments === 0 && {
comments: {
none: {},
},
}),
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
@@ -176,14 +170,116 @@ export const resumesResumeUserRouter = createProtectedRouter()
};
return resume;
});
return { mappedResumeData, totalRecords };
const roleCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
},
by: ['role'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
stars: {
some: {
userId,
},
},
title: { contains: searchValue, mode: 'insensitive' },
},
});
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: {
_all: true,
},
by: ['experience'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
stars: {
some: {
userId,
},
},
title: { contains: searchValue, mode: 'insensitive' },
},
});
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'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
stars: {
some: {
userId,
},
},
title: { contains: searchValue, mode: 'insensitive' },
},
});
const mappedLocationCounts = Object.fromEntries(
locationCounts.map((lc) => [lc.location, 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,
};
return { filterCounts, mappedResumeData, totalRecords };
},
})
.query('findUserCreated', {
input: z.object({
experienceFilters: z.string().array(),
isUnreviewed: z.boolean(),
locationFilters: z.string().array(),
numComments: z.number().optional(),
roleFilters: z.string().array(),
searchValue: z.string(),
skip: z.number(),
@@ -198,18 +294,14 @@ export const resumesResumeUserRouter = createProtectedRouter()
experienceFilters,
sortOrder,
searchValue,
numComments,
isUnreviewed,
take,
skip,
} = input;
const totalRecords = await ctx.prisma.resumesResume.count({
where: {
...(numComments === 0 && {
comments: {
none: {},
},
}),
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
@@ -250,12 +342,8 @@ export const resumesResumeUserRouter = createProtectedRouter()
skip,
take,
where: {
...(numComments === 0 && {
comments: {
none: {},
},
}),
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
@@ -280,6 +368,96 @@ export const resumesResumeUserRouter = createProtectedRouter()
};
return resume;
});
return { mappedResumeData, totalRecords };
const roleCounts = await ctx.prisma.resumesResume.groupBy({
_count: {
_all: true,
},
by: ['role'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
},
});
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: {
_all: true,
},
by: ['experience'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
},
});
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'],
where: {
experience: { in: experienceFilters },
isResolved: isUnreviewed ? false : {},
location: { in: locationFilters },
role: { in: roleFilters },
title: { contains: searchValue, mode: 'insensitive' },
userId,
},
});
const mappedLocationCounts = Object.fromEntries(
locationCounts.map((lc) => [lc.location, 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,
};
return { filterCounts, mappedResumeData, totalRecords };
},
});