mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-31 06:03:55 +08:00
[resumes][feat] Fetch resume details from database (#322)
* [resumes][feat] Add resume details router * [resumes][feat] Change review page to dynamic routing * [resumes][feat] Toggle resume star button * [resumes][refactor] Revert routers to User model
This commit is contained in:
@ -2,6 +2,7 @@ import superjson from 'superjson';
|
||||
|
||||
import { createRouter } from './context';
|
||||
import { protectedExampleRouter } from './protected-example-router';
|
||||
import { resumesDetailsRouter } from './resumes-details-router';
|
||||
import { resumesResumeUserRouter } from './resumes-resume-user-router';
|
||||
import { resumeReviewsRouter } from './resumes-reviews-router';
|
||||
import { resumesReviewsUserRouter } from './resumes-reviews-user-router';
|
||||
@ -16,6 +17,7 @@ export const appRouter = createRouter()
|
||||
.merge('auth.', protectedExampleRouter)
|
||||
.merge('todos.', todosRouter)
|
||||
.merge('todos.user.', todosUserRouter)
|
||||
.merge('resumes.details.', resumesDetailsRouter)
|
||||
.merge('resumes.resume.user.', resumesResumeUserRouter)
|
||||
.merge('resumes.reviews.', resumeReviewsRouter)
|
||||
.merge('resumes.reviews.user.', resumesReviewsUserRouter);
|
||||
|
79
apps/portal/src/server/router/resumes-details-router.ts
Normal file
79
apps/portal/src/server/router/resumes-details-router.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { createRouter } from './context';
|
||||
|
||||
export const resumesDetailsRouter = createRouter()
|
||||
.query('find', {
|
||||
input: z.object({
|
||||
resumeId: z.string(),
|
||||
}),
|
||||
async resolve({ ctx, input }) {
|
||||
const { resumeId } = input;
|
||||
const userId = ctx.session?.user?.id;
|
||||
|
||||
// Use the resumeId to query all related information of a single resume
|
||||
// from Resumesresume:
|
||||
return await ctx.prisma.resumesResume.findUnique({
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
stars: true,
|
||||
},
|
||||
},
|
||||
stars: {
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
select: {
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
id: resumeId,
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
.mutation('update_star', {
|
||||
input: z.object({
|
||||
resumeId: z.string(),
|
||||
}),
|
||||
async resolve({ ctx, input }) {
|
||||
const { resumeId } = input;
|
||||
// Update_star will only be called if user is logged in
|
||||
const userId = ctx.session!.user!.id;
|
||||
|
||||
// Use the resumeId and resumeProfileId to check if star exists
|
||||
const resumesStar = await ctx.prisma.resumesStar.findUnique({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
where: {
|
||||
userId_resumeId: {
|
||||
resumeId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (resumesStar === null) {
|
||||
return await ctx.prisma.resumesStar.create({
|
||||
data: {
|
||||
resumeId,
|
||||
userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
return await ctx.prisma.resumesStar.delete({
|
||||
where: {
|
||||
userId_resumeId: {
|
||||
resumeId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
@ -15,23 +15,12 @@ export const resumesResumeUserRouter = createProtectedRouter().mutation(
|
||||
}),
|
||||
async resolve({ ctx, input }) {
|
||||
const userId = ctx.session?.user.id;
|
||||
const resumeProfile = await ctx.prisma.resumesProfile.upsert({
|
||||
create: {
|
||||
userId,
|
||||
},
|
||||
update: {},
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: Store file in file storage and retrieve URL
|
||||
|
||||
return await ctx.prisma.resumesResume.create({
|
||||
data: {
|
||||
...input,
|
||||
resumesProfileId: resumeProfile.id,
|
||||
url: '',
|
||||
userId,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
@ -7,18 +7,9 @@ export const resumeReviewsRouter = createRouter().query('list', {
|
||||
resumeId: z.string(),
|
||||
}),
|
||||
async resolve({ ctx, input }) {
|
||||
const userId = ctx.session?.user?.id;
|
||||
const { resumeId } = input;
|
||||
|
||||
const { resumesProfileId } =
|
||||
await ctx.prisma.resumesResume.findUniqueOrThrow({
|
||||
select: {
|
||||
resumesProfileId: true,
|
||||
},
|
||||
where: {
|
||||
id: resumeId,
|
||||
},
|
||||
});
|
||||
|
||||
// For this resume, we retrieve every comment's information, along with:
|
||||
// The user's name and image to render
|
||||
// Number of votes, and whether the user (if-any) has voted
|
||||
@ -29,20 +20,16 @@ export const resumeReviewsRouter = createRouter().query('list', {
|
||||
votes: true,
|
||||
},
|
||||
},
|
||||
resumesProfile: {
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
image: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
select: {
|
||||
image: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
votes: {
|
||||
take: 1,
|
||||
where: {
|
||||
resumesProfileId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -6,8 +6,8 @@ import { createProtectedRouter } from './context';
|
||||
type IResumeCommentInput = Readonly<{
|
||||
description: string;
|
||||
resumeId: string;
|
||||
resumesProfileId: string;
|
||||
section: ResumesSection;
|
||||
userId: string;
|
||||
}>;
|
||||
|
||||
export const resumesReviewsUserRouter = createProtectedRouter().mutation(
|
||||
@ -22,19 +22,10 @@ export const resumesReviewsUserRouter = createProtectedRouter().mutation(
|
||||
skills: z.string(),
|
||||
}),
|
||||
async resolve({ ctx, input }) {
|
||||
const userId = ctx.session?.user?.id;
|
||||
const { resumeId, education, experience, general, projects, skills } =
|
||||
input;
|
||||
|
||||
const { resumesProfileId } =
|
||||
await ctx.prisma.resumesResume.findUniqueOrThrow({
|
||||
select: {
|
||||
resumesProfileId: true,
|
||||
},
|
||||
where: {
|
||||
id: resumeId,
|
||||
},
|
||||
});
|
||||
|
||||
// For each section, convert them into ResumesComment model if provided
|
||||
const comments: Array<IResumeCommentInput> = [
|
||||
{ description: education, section: ResumesSection.EDUCATION },
|
||||
@ -50,8 +41,8 @@ export const resumesReviewsUserRouter = createProtectedRouter().mutation(
|
||||
return {
|
||||
description,
|
||||
resumeId,
|
||||
resumesProfileId,
|
||||
section,
|
||||
userId,
|
||||
};
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user