mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2026-04-04 03:18:05 +08:00
[resumes][feat] Add top 10 shortcut (#518)
This commit is contained in:
@@ -187,6 +187,7 @@ export default function ResumeHomePage() {
|
||||
'resumes.resume.findAll',
|
||||
{
|
||||
experienceFilters: userFilters.experience.map(({ value }) => value),
|
||||
isTop10: userFilters.isTop10,
|
||||
isUnreviewed: userFilters.isUnreviewed,
|
||||
locationFilters: userFilters.location.map(({ value }) => value),
|
||||
roleFilters: userFilters.role.map(({ value }) => value),
|
||||
@@ -206,6 +207,7 @@ export default function ResumeHomePage() {
|
||||
'resumes.resume.user.findUserStarred',
|
||||
{
|
||||
experienceFilters: userFilters.experience.map(({ value }) => value),
|
||||
isTop10: userFilters.isTop10,
|
||||
isUnreviewed: userFilters.isUnreviewed,
|
||||
locationFilters: userFilters.location.map(({ value }) => value),
|
||||
roleFilters: userFilters.role.map(({ value }) => value),
|
||||
@@ -226,6 +228,7 @@ export default function ResumeHomePage() {
|
||||
'resumes.resume.user.findUserCreated',
|
||||
{
|
||||
experienceFilters: userFilters.experience.map(({ value }) => value),
|
||||
isTop10: userFilters.isTop10,
|
||||
isUnreviewed: userFilters.isUnreviewed,
|
||||
locationFilters: userFilters.location.map(({ value }) => value),
|
||||
roleFilters: userFilters.role.map(({ value }) => value),
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
import { Vote } from '@prisma/client';
|
||||
|
||||
import type { FilterCounts } from '~/utils/resumes/resumeFilters';
|
||||
import { resumeGetFilterCounts } from '~/utils/resumes/resumeGetFilterCounts';
|
||||
|
||||
import { createRouter } from '../context';
|
||||
|
||||
import type { Resume } from '~/types/resume';
|
||||
@@ -9,6 +12,7 @@ export const resumesRouter = createRouter()
|
||||
.query('findAll', {
|
||||
input: z.object({
|
||||
experienceFilters: z.string().array(),
|
||||
isTop10: z.boolean(),
|
||||
isUnreviewed: z.boolean(),
|
||||
locationFilters: z.string().array(),
|
||||
roleFilters: z.string().array(),
|
||||
@@ -25,19 +29,14 @@ export const resumesRouter = createRouter()
|
||||
sortOrder,
|
||||
isUnreviewed,
|
||||
skip,
|
||||
isTop10,
|
||||
searchValue,
|
||||
take,
|
||||
} = input;
|
||||
const userId = ctx.session?.user?.id;
|
||||
const totalRecords = await ctx.prisma.resumesResume.count({
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
let totalRecords = 10;
|
||||
let filterCounts = {} as FilterCounts;
|
||||
|
||||
const resumesData = await ctx.prisma.resumesResume.findMany({
|
||||
include: {
|
||||
_count: {
|
||||
@@ -77,7 +76,7 @@ export const resumesRouter = createRouter()
|
||||
},
|
||||
}
|
||||
: { comments: { _count: 'desc' } },
|
||||
skip,
|
||||
skip: isTop10 ? 0 : skip,
|
||||
take,
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
@@ -107,62 +106,76 @@ export const resumesRouter = createRouter()
|
||||
return resume;
|
||||
});
|
||||
|
||||
// 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,
|
||||
},
|
||||
by: ['role'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
if (isTop10) {
|
||||
filterCounts = resumeGetFilterCounts(mappedResumeData);
|
||||
} else {
|
||||
totalRecords = await ctx.prisma.resumesResume.count({
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { 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]),
|
||||
);
|
||||
// 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,
|
||||
},
|
||||
by: ['role'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
|
||||
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['experience'],
|
||||
where: {
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedExperienceCounts = Object.fromEntries(
|
||||
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
|
||||
);
|
||||
// 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]),
|
||||
);
|
||||
|
||||
const locationCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['locationId'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedLocationCounts = Object.fromEntries(
|
||||
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
|
||||
);
|
||||
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['experience'],
|
||||
where: {
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedExperienceCounts = Object.fromEntries(
|
||||
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
|
||||
);
|
||||
|
||||
const filterCounts = {
|
||||
experience: mappedExperienceCounts,
|
||||
location: mappedLocationCounts,
|
||||
role: mappedRoleCounts,
|
||||
};
|
||||
const locationCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['locationId'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedLocationCounts = Object.fromEntries(
|
||||
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
|
||||
);
|
||||
|
||||
filterCounts = {
|
||||
experience: mappedExperienceCounts,
|
||||
location: mappedLocationCounts,
|
||||
role: mappedRoleCounts,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
filterCounts,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { FilterCounts } from '~/utils/resumes/resumeFilters';
|
||||
import { resumeGetFilterCounts } from '~/utils/resumes/resumeGetFilterCounts';
|
||||
|
||||
import { createProtectedRouter } from '../context';
|
||||
|
||||
import type { Resume } from '~/types/resume';
|
||||
@@ -63,6 +66,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
.query('findUserStarred', {
|
||||
input: z.object({
|
||||
experienceFilters: z.string().array(),
|
||||
isTop10: z.boolean(),
|
||||
isUnreviewed: z.boolean(),
|
||||
locationFilters: z.string().array(),
|
||||
roleFilters: z.string().array(),
|
||||
@@ -78,23 +82,16 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
locationFilters,
|
||||
experienceFilters,
|
||||
searchValue,
|
||||
isTop10,
|
||||
sortOrder,
|
||||
isUnreviewed,
|
||||
skip,
|
||||
take,
|
||||
} = input;
|
||||
const totalRecords = await ctx.prisma.resumesStar.count({
|
||||
where: {
|
||||
resume: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
userId,
|
||||
},
|
||||
});
|
||||
|
||||
let totalRecords = 10;
|
||||
let filterCounts = {} as FilterCounts;
|
||||
|
||||
const resumeStarsData = await ctx.prisma.resumesStar.findMany({
|
||||
include: {
|
||||
resume: {
|
||||
@@ -140,7 +137,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
},
|
||||
},
|
||||
},
|
||||
skip,
|
||||
skip: isTop10 ? 0 : skip,
|
||||
take,
|
||||
where: {
|
||||
resume: {
|
||||
@@ -174,74 +171,91 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
return resume;
|
||||
});
|
||||
|
||||
const roleCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['role'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
stars: {
|
||||
some: {
|
||||
userId,
|
||||
if (isTop10) {
|
||||
filterCounts = resumeGetFilterCounts(mappedResumeData);
|
||||
} else {
|
||||
totalRecords = await ctx.prisma.resumesStar.count({
|
||||
where: {
|
||||
resume: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
userId,
|
||||
},
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedRoleCounts = Object.fromEntries(
|
||||
roleCounts.map((rc) => [rc.role, rc._count._all]),
|
||||
);
|
||||
});
|
||||
|
||||
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['experience'],
|
||||
where: {
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
stars: {
|
||||
some: {
|
||||
userId,
|
||||
const roleCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['role'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
stars: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedExperienceCounts = Object.fromEntries(
|
||||
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
|
||||
);
|
||||
});
|
||||
const mappedRoleCounts = Object.fromEntries(
|
||||
roleCounts.map((rc) => [rc.role, rc._count._all]),
|
||||
);
|
||||
|
||||
const locationCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['locationId'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
role: { in: roleFilters },
|
||||
stars: {
|
||||
some: {
|
||||
userId,
|
||||
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['experience'],
|
||||
where: {
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
stars: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedLocationCounts = Object.fromEntries(
|
||||
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
|
||||
);
|
||||
});
|
||||
const mappedExperienceCounts = Object.fromEntries(
|
||||
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
|
||||
);
|
||||
|
||||
const filterCounts = {
|
||||
experience: mappedExperienceCounts,
|
||||
location: mappedLocationCounts,
|
||||
role: mappedRoleCounts,
|
||||
};
|
||||
const locationCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['locationId'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
role: { in: roleFilters },
|
||||
stars: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
},
|
||||
});
|
||||
const mappedLocationCounts = Object.fromEntries(
|
||||
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
|
||||
);
|
||||
|
||||
filterCounts = {
|
||||
experience: mappedExperienceCounts,
|
||||
location: mappedLocationCounts,
|
||||
role: mappedRoleCounts,
|
||||
};
|
||||
}
|
||||
|
||||
return { filterCounts, mappedResumeData, totalRecords };
|
||||
},
|
||||
@@ -249,6 +263,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
.query('findUserCreated', {
|
||||
input: z.object({
|
||||
experienceFilters: z.string().array(),
|
||||
isTop10: z.boolean(),
|
||||
isUnreviewed: z.boolean(),
|
||||
locationFilters: z.string().array(),
|
||||
roleFilters: z.string().array(),
|
||||
@@ -265,20 +280,15 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
experienceFilters,
|
||||
sortOrder,
|
||||
searchValue,
|
||||
isTop10,
|
||||
isUnreviewed,
|
||||
take,
|
||||
skip,
|
||||
} = input;
|
||||
const totalRecords = await ctx.prisma.resumesResume.count({
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
|
||||
let totalRecords = 10;
|
||||
let filterCounts = {} as FilterCounts;
|
||||
|
||||
const resumesData = await ctx.prisma.resumesResume.findMany({
|
||||
include: {
|
||||
_count: {
|
||||
@@ -315,7 +325,7 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
},
|
||||
}
|
||||
: { comments: { _count: 'desc' } },
|
||||
skip,
|
||||
skip: isTop10 ? 0 : skip,
|
||||
take,
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
@@ -346,62 +356,77 @@ export const resumesResumeUserRouter = createProtectedRouter()
|
||||
return resume;
|
||||
});
|
||||
|
||||
const roleCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['role'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const mappedRoleCounts = Object.fromEntries(
|
||||
roleCounts.map((rc) => [rc.role, rc._count._all]),
|
||||
);
|
||||
if (isTop10) {
|
||||
filterCounts = resumeGetFilterCounts(mappedResumeData);
|
||||
} else {
|
||||
totalRecords = await ctx.prisma.resumesResume.count({
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
|
||||
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['experience'],
|
||||
where: {
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const mappedExperienceCounts = Object.fromEntries(
|
||||
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
|
||||
);
|
||||
const roleCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['role'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const mappedRoleCounts = Object.fromEntries(
|
||||
roleCounts.map((rc) => [rc.role, rc._count._all]),
|
||||
);
|
||||
|
||||
const locationCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['locationId'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const mappedLocationCounts = Object.fromEntries(
|
||||
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
|
||||
);
|
||||
const experienceCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['experience'],
|
||||
where: {
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
locationId: { in: locationFilters },
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const mappedExperienceCounts = Object.fromEntries(
|
||||
experienceCounts.map((ec) => [ec.experience, ec._count._all]),
|
||||
);
|
||||
|
||||
const filterCounts = {
|
||||
experience: mappedExperienceCounts,
|
||||
location: mappedLocationCounts,
|
||||
role: mappedRoleCounts,
|
||||
};
|
||||
const locationCounts = await ctx.prisma.resumesResume.groupBy({
|
||||
_count: {
|
||||
_all: true,
|
||||
},
|
||||
by: ['locationId'],
|
||||
where: {
|
||||
experience: { in: experienceFilters },
|
||||
isResolved: isUnreviewed ? false : {},
|
||||
role: { in: roleFilters },
|
||||
title: { contains: searchValue, mode: 'insensitive' },
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const mappedLocationCounts = Object.fromEntries(
|
||||
locationCounts.map((lc) => [lc.locationId, lc._count._all]),
|
||||
);
|
||||
|
||||
filterCounts = {
|
||||
experience: mappedExperienceCounts,
|
||||
location: mappedLocationCounts,
|
||||
role: mappedRoleCounts,
|
||||
};
|
||||
}
|
||||
|
||||
return { filterCounts, mappedResumeData, totalRecords };
|
||||
},
|
||||
|
||||
@@ -5,8 +5,10 @@ import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
|
||||
import { JobTitleLabels } from '~/components/shared/JobTitles';
|
||||
|
||||
export type FilterId = 'experience' | 'location' | 'role';
|
||||
export type FilterCounts = Record<FilterId, Record<string, number>>;
|
||||
|
||||
export type CustomFilter = {
|
||||
isTop10: boolean;
|
||||
isUnreviewed: boolean;
|
||||
};
|
||||
|
||||
@@ -145,6 +147,7 @@ export const INITIAL_LOCATIONS: Array<TypeaheadOption> = [
|
||||
|
||||
export const INITIAL_FILTER_STATE: FilterState = {
|
||||
experience: EXPERIENCES,
|
||||
isTop10: false,
|
||||
isUnreviewed: true,
|
||||
location: INITIAL_LOCATIONS,
|
||||
role: INITIAL_ROLES,
|
||||
@@ -185,6 +188,7 @@ export const SHORTCUTS: Array<Shortcut> = [
|
||||
{
|
||||
filters: {
|
||||
...INITIAL_FILTER_STATE,
|
||||
isTop10: true,
|
||||
isUnreviewed: false,
|
||||
},
|
||||
name: 'Top 10',
|
||||
|
||||
39
apps/portal/src/utils/resumes/resumeGetFilterCounts.ts
Normal file
39
apps/portal/src/utils/resumes/resumeGetFilterCounts.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { Resume } from '~/types/resume';
|
||||
|
||||
export function resumeGetFilterCounts(data: Array<Resume>) {
|
||||
const roleCounts: Record<string, number> = {};
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const { role } = data[i];
|
||||
if (!(role in roleCounts)) {
|
||||
roleCounts[role] = 1;
|
||||
} else {
|
||||
roleCounts[role]++;
|
||||
}
|
||||
}
|
||||
|
||||
const experienceCounts: Record<string, number> = {};
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const { experience } = data[i];
|
||||
if (!(experience in experienceCounts)) {
|
||||
experienceCounts[experience] = 1;
|
||||
} else {
|
||||
experienceCounts[experience]++;
|
||||
}
|
||||
}
|
||||
|
||||
const locationCounts: Record<string, number> = {};
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const { locationId } = data[i];
|
||||
if (!(locationId in locationCounts)) {
|
||||
locationCounts[locationId] = 1;
|
||||
} else {
|
||||
locationCounts[locationId]++;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
experience: experienceCounts,
|
||||
location: locationCounts,
|
||||
role: roleCounts,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user