mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-28 04:33:42 +08:00
[resumes][feat] auto-resolve resume when comments >= 5
This commit is contained in:
@ -8,19 +8,30 @@ type Props = Readonly<{
|
|||||||
userId: string;
|
userId: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
const STALE_TIME = 60;
|
||||||
|
|
||||||
export default function ResumeUserBadges({ userId }: Props) {
|
export default function ResumeUserBadges({ userId }: Props) {
|
||||||
const userReviewedResumeCountQuery = trpc.useQuery([
|
const userReviewedResumeCountQuery = trpc.useQuery(
|
||||||
'resumes.resume.findUserReviewedResumeCount',
|
['resumes.resume.findUserReviewedResumeCount', { userId }],
|
||||||
{ userId },
|
{
|
||||||
]);
|
retry: false,
|
||||||
const userMaxResumeUpvoteCountQuery = trpc.useQuery([
|
staleTime: STALE_TIME,
|
||||||
'resumes.resume.findUserMaxResumeUpvoteCount',
|
},
|
||||||
{ userId },
|
);
|
||||||
]);
|
const userMaxResumeUpvoteCountQuery = trpc.useQuery(
|
||||||
const userTopUpvotedCommentCountQuery = trpc.useQuery([
|
['resumes.resume.findUserMaxResumeUpvoteCount', { userId }],
|
||||||
'resumes.resume.findUserTopUpvotedCommentCount',
|
{
|
||||||
{ userId },
|
retry: false,
|
||||||
]);
|
staleTime: STALE_TIME,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const userTopUpvotedCommentCountQuery = trpc.useQuery(
|
||||||
|
['resumes.resume.findUserTopUpvotedCommentCount', { userId }],
|
||||||
|
{
|
||||||
|
retry: false,
|
||||||
|
staleTime: STALE_TIME,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const payload: BadgePayload = {
|
const payload: BadgePayload = {
|
||||||
maxResumeUpvoteCount: userMaxResumeUpvoteCountQuery.data ?? 0,
|
maxResumeUpvoteCount: userMaxResumeUpvoteCountQuery.data ?? 0,
|
||||||
|
@ -34,7 +34,18 @@ export default function ResumeListItem({ href, resumeInfo }: Props) {
|
|||||||
<div className="grid grid-cols-8">
|
<div className="grid grid-cols-8">
|
||||||
<div className="col-span-7 grid gap-4 border-b border-slate-200 p-4 hover:bg-slate-100 sm:grid-cols-7">
|
<div className="col-span-7 grid gap-4 border-b border-slate-200 p-4 hover:bg-slate-100 sm:grid-cols-7">
|
||||||
<div className="sm:col-span-4">
|
<div className="sm:col-span-4">
|
||||||
{resumeInfo.title}
|
<div className="flex items-center gap-3">
|
||||||
|
<p>{resumeInfo.title}</p>
|
||||||
|
{resumeInfo.isResolved ? (
|
||||||
|
<p className="rounded-xl border border-slate-200 p-1 text-xs text-slate-300">
|
||||||
|
Reviewed
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p className="rounded-xl border border-slate-400 p-1 text-xs text-slate-500">
|
||||||
|
Unreviewed
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div className="text-primary-500 mt-2 flex items-center justify-start text-xs">
|
<div className="text-primary-500 mt-2 flex items-center justify-start text-xs">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<BriefcaseIcon
|
<BriefcaseIcon
|
||||||
|
@ -53,18 +53,38 @@ export default function ResumeCommentsForm({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
const invalidateResumeQueries = () => {
|
||||||
|
trpcContext.invalidateQueries(['resumes.resume.findOne']);
|
||||||
|
trpcContext.invalidateQueries(['resumes.resume.findAll']);
|
||||||
|
trpcContext.invalidateQueries(['resumes.resume.user.findUserStarred']);
|
||||||
|
trpcContext.invalidateQueries(['resumes.resume.user.findUserCreated']);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolveMutation = trpc.useMutation('resumes.resume.user.resolve', {
|
||||||
|
onSuccess() {
|
||||||
|
invalidateResumeQueries();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: Give a feedback to the user if the action succeeds/fails
|
// TODO: Give a feedback to the user if the action succeeds/fails
|
||||||
const onSubmit: SubmitHandler<IFormInput> = async (data) => {
|
const onSubmit: SubmitHandler<IFormInput> = async (formData) => {
|
||||||
return await commentCreateMutation.mutate(
|
return await commentCreateMutation.mutate(
|
||||||
{
|
{
|
||||||
resumeId,
|
resumeId,
|
||||||
...data,
|
...formData,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: (data) => {
|
||||||
// Redirect back to comments section
|
// Redirect back to comments section
|
||||||
setShowCommentsForm(false);
|
setShowCommentsForm(false);
|
||||||
|
const { prevCount, newCount } = data;
|
||||||
|
// Auto mark resume as resolved once the total comments passes the 5 threshold
|
||||||
|
if (newCount >= 5 && prevCount < 5) {
|
||||||
|
resolveMutation.mutate({
|
||||||
|
id: resumeId,
|
||||||
|
val: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -471,6 +471,7 @@ export default function ResumeHomePage() {
|
|||||||
<main className="h-full flex-auto px-8 pb-4">
|
<main className="h-full flex-auto px-8 pb-4">
|
||||||
<div className="flex justify-start">
|
<div className="flex justify-start">
|
||||||
<div className="fixed top-0 bottom-0 mt-24 hidden w-64 overflow-auto lg:block">
|
<div className="fixed top-0 bottom-0 mt-24 hidden w-64 overflow-auto lg:block">
|
||||||
|
{/* Quick Access Section */}
|
||||||
<h3 className="text-md font-medium tracking-tight text-gray-900">
|
<h3 className="text-md font-medium tracking-tight text-gray-900">
|
||||||
Quick access
|
Quick access
|
||||||
</h3>
|
</h3>
|
||||||
@ -489,6 +490,7 @@ export default function ResumeHomePage() {
|
|||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
{/* Filter Section */}
|
||||||
<h3 className="text-md font-medium tracking-tight text-slate-900">
|
<h3 className="text-md font-medium tracking-tight text-slate-900">
|
||||||
Explore these filters
|
Explore these filters
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -45,9 +45,19 @@ export const resumesCommentsUserRouter = createProtectedRouter()
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return await ctx.prisma.resumesComment.createMany({
|
const prevCommentCount = await ctx.prisma.resumesComment.count({
|
||||||
|
where: {
|
||||||
|
resumeId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const result = await ctx.prisma.resumesComment.createMany({
|
||||||
data: comments,
|
data: comments,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
newCount: Number(prevCommentCount) + result.count,
|
||||||
|
prevCount: prevCommentCount,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.mutation('update', {
|
.mutation('update', {
|
||||||
|
Reference in New Issue
Block a user