add suggestion backend

This commit is contained in:
Kalle 2021-02-23 22:20:22 +02:00
parent 32115798e2
commit e787a94de6
5 changed files with 80 additions and 11 deletions

View File

@ -2,6 +2,6 @@ import { User } from "@prisma/client";
import { NextApiRequest } from "next";
import { getSession } from "next-auth/client";
export const getMySession = (req?: NextApiRequest): Promise<User | null> =>
export const getMySession = (req: NextApiRequest): Promise<User | null> =>
// @ts-expect-error
getSession({ req });

6
lib/errors.ts Normal file
View File

@ -0,0 +1,6 @@
export class UserError extends Error {
constructor(message: string) {
super(message);
this.name = "UserError";
}
}

View File

@ -4,7 +4,7 @@ export const SUGGESTION_DESCRIPTION_LIMIT = 500;
export const suggestionSchema = z.object({
description: z.string().max(SUGGESTION_DESCRIPTION_LIMIT),
suggestedUserId: z.number().int(),
suggestedId: z.number().int(),
tier: z.number().int().min(1).max(3),
region: z.enum(["NA", "EU"]),
});

View File

@ -0,0 +1,42 @@
import { getMySession } from "lib/api";
import { UserError } from "lib/errors";
import { NextApiRequest, NextApiResponse } from "next";
import plusService from "services/plus";
import { ZodError } from "zod";
const suggestionsHandler = async (
req: NextApiRequest,
res: NextApiResponse
) => {
const user = await getMySession(req);
switch (req.method) {
case "POST":
await postHandler(req, res);
break;
default:
res.status(405).end();
}
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
if (!user) return res.status(401).end();
try {
await plusService.addSuggestion({ data: req.body, userId: user.id });
} catch (e) {
if (e instanceof ZodError) {
res.status(400).json({ message: e.message });
} else if (e instanceof UserError) {
res.status(400).json({ message: e.message });
} else {
res.status(500).end();
}
return;
}
res.status(200).end();
}
};
export default suggestionsHandler;

View File

@ -1,6 +1,8 @@
import { Prisma } from "@prisma/client";
import { UserError } from "lib/errors";
import { getPercentageFromCounts } from "lib/plus";
import { userBasicSelection } from "lib/prisma";
import { suggestionSchema } from "lib/validators/suggestion";
import prisma from "prisma/client";
export type VotingSummariesByMonthAndTier = Prisma.PromiseReturnType<
@ -102,25 +104,44 @@ const addSuggestion = async ({
data,
userId,
}: {
data: Prisma.PlusSuggestionUncheckedCreateInput;
data: unknown;
userId: number;
}) => {
const existingSuggestion = await prisma.plusSuggestion.findUnique({
where: { tier_suggestedId_suggesterId: data },
});
const parsedData = { ...suggestionSchema.parse(data), suggesterId: userId };
const [suggestions, plusStatus] = await Promise.all([
prisma.plusSuggestion.findMany({}),
prisma.plusStatus.findUnique({ where: { userId } }),
]);
const existingSuggestion = suggestions.find(
({ tier, suggestedId }) =>
tier === parsedData.tier && suggestedId === parsedData.suggestedId
);
// every user can only send one new suggestion per month
if (!existingSuggestion) {
const usersSuggestion = await prisma.plusSuggestion.findFirst({
where: { isResuggestion: false, suggesterId: userId },
});
const usersSuggestion = suggestions.find(
({ isResuggestion, suggesterId }) =>
isResuggestion === false && suggesterId === userId
);
if (usersSuggestion) {
throw Error("Already made a new suggestion");
throw new UserError("already made a new suggestion");
}
}
if (
!plusStatus ||
!plusStatus.membershipTier ||
plusStatus.membershipTier > parsedData.tier
) {
throw new UserError(
"not a member of high enough tier to suggest for this tier"
);
}
// TODO voting has started
return prisma.plusSuggestion.create({
data: { ...data, isResuggestion: !!existingSuggestion },
data: { ...parsedData, isResuggestion: !!existingSuggestion },
});
};