diff --git a/apps/portal/src/server/router/index.ts b/apps/portal/src/server/router/index.ts index 99e32b83..3d20bff5 100644 --- a/apps/portal/src/server/router/index.ts +++ b/apps/portal/src/server/router/index.ts @@ -7,11 +7,17 @@ import { offersAnalysisRouter } from './offers/offers-analysis-router'; import { offersCommentsRouter } from './offers/offers-comments-router'; import { offersProfileRouter } from './offers/offers-profile-router'; import { protectedExampleRouter } from './protected-example-router'; -import { questionsAnswerCommentRouter } from './questions-answer-comment-router'; -import { questionsAnswerRouter } from './questions-answer-router'; -import { questionsQuestionCommentRouter } from './questions-question-comment-router'; -import { questionsQuestionEncounterRouter } from './questions-question-encounter-router'; -import { questionsQuestionRouter } from './questions-question-router'; +import { questionsAnswerCommentRouter } from './questions/questions-answer-comment-router'; +import { questionsAnswerCommentUserRouter } from './questions/questions-answer-comment-user-router'; +import { questionsAnswerRouter } from './questions/questions-answer-router'; +import { questionsAnswerUserRouter } from './questions/questions-answer-user-router'; +import { questionsListRouter } from './questions/questions-list-router'; +import { questionsQuestionCommentRouter } from './questions/questions-question-comment-router'; +import { questionsQuestionCommentUserRouter } from './questions/questions-question-comment-user-router'; +import { questionsQuestionEncounterRouter } from './questions/questions-question-encounter-router'; +import { questionsQuestionEncounterUserRouter } from './questions/questions-question-encounter-user-router'; +import { questionsQuestionRouter } from './questions/questions-question-router'; +import { questionsQuestionUserRouter } from './questions/questions-question-user-router'; import { resumeCommentsRouter } from './resumes/resumes-comments-router'; import { resumesCommentsUserRouter } from './resumes/resumes-comments-user-router'; import { resumesCommentsVotesRouter } from './resumes/resumes-comments-votes-router'; @@ -39,10 +45,22 @@ export const appRouter = createRouter() .merge('resumes.comments.votes.', resumesCommentsVotesRouter) .merge('resumes.comments.votes.user.', resumesCommentsVotesUserRouter) .merge('questions.answers.comments.', questionsAnswerCommentRouter) + .merge('questions.answers.comments.user.', questionsAnswerCommentUserRouter) .merge('questions.answers.', questionsAnswerRouter) + .merge('questions.lists.', questionsListRouter) + .merge('questions.answers.user.', questionsAnswerUserRouter) .merge('questions.questions.comments.', questionsQuestionCommentRouter) + .merge( + 'questions.questions.comments.user.', + questionsQuestionCommentUserRouter, + ) .merge('questions.questions.encounters.', questionsQuestionEncounterRouter) + .merge( + 'questions.questions.encounters.user.', + questionsQuestionEncounterUserRouter, + ) .merge('questions.questions.', questionsQuestionRouter) + .merge('questions.questions.user.', questionsQuestionUserRouter) .merge('offers.', offersRouter) .merge('offers.profile.', offersProfileRouter) .merge('offers.analysis.', offersAnalysisRouter) diff --git a/apps/portal/src/server/router/questions/questions-answer-comment-router.ts b/apps/portal/src/server/router/questions/questions-answer-comment-router.ts new file mode 100644 index 00000000..2ecd51b7 --- /dev/null +++ b/apps/portal/src/server/router/questions/questions-answer-comment-router.ts @@ -0,0 +1,64 @@ +import { z } from 'zod'; +import { Vote } from '@prisma/client'; + +import { createRouter } from '../context'; + +import type { AnswerComment } from '~/types/questions'; + +export const questionsAnswerCommentRouter = createRouter().query( + 'getAnswerComments', + { + input: z.object({ + answerId: z.string(), + }), + async resolve({ ctx, input }) { + const questionAnswerCommentsData = + await ctx.prisma.questionsAnswerComment.findMany({ + include: { + user: { + select: { + image: true, + name: true, + }, + }, + votes: true, + }, + orderBy: { + createdAt: 'desc', + }, + where: { + answerId: input.answerId, + }, + }); + return questionAnswerCommentsData.map((data) => { + const votes: number = data.votes.reduce( + (previousValue: number, currentValue) => { + let result: number = previousValue; + + switch (currentValue.vote) { + case Vote.UPVOTE: + result += 1; + break; + case Vote.DOWNVOTE: + result -= 1; + break; + } + return result; + }, + 0, + ); + + const answerComment: AnswerComment = { + content: data.content, + createdAt: data.createdAt, + id: data.id, + numVotes: votes, + updatedAt: data.updatedAt, + user: data.user?.name ?? '', + userImage: data.user?.image ?? '', + }; + return answerComment; + }); + }, + }, +); diff --git a/apps/portal/src/server/router/questions-answer-comment-router.ts b/apps/portal/src/server/router/questions/questions-answer-comment-user-router.ts similarity index 77% rename from apps/portal/src/server/router/questions-answer-comment-router.ts rename to apps/portal/src/server/router/questions/questions-answer-comment-user-router.ts index 63a9ede4..d55e590c 100644 --- a/apps/portal/src/server/router/questions-answer-comment-router.ts +++ b/apps/portal/src/server/router/questions/questions-answer-comment-user-router.ts @@ -2,65 +2,9 @@ import { z } from 'zod'; import { Vote } from '@prisma/client'; import { TRPCError } from '@trpc/server'; -import { createProtectedRouter } from './context'; +import { createProtectedRouter } from '../context'; -import type { AnswerComment } from '~/types/questions'; - -export const questionsAnswerCommentRouter = createProtectedRouter() - .query('getAnswerComments', { - input: z.object({ - answerId: z.string(), - }), - async resolve({ ctx, input }) { - const questionAnswerCommentsData = - await ctx.prisma.questionsAnswerComment.findMany({ - include: { - user: { - select: { - image: true, - name: true, - }, - }, - votes: true, - }, - orderBy: { - createdAt: 'desc', - }, - where: { - answerId: input.answerId, - }, - }); - return questionAnswerCommentsData.map((data) => { - const votes: number = data.votes.reduce( - (previousValue: number, currentValue) => { - let result: number = previousValue; - - switch (currentValue.vote) { - case Vote.UPVOTE: - result += 1; - break; - case Vote.DOWNVOTE: - result -= 1; - break; - } - return result; - }, - 0, - ); - - const answerComment: AnswerComment = { - content: data.content, - createdAt: data.createdAt, - id: data.id, - numVotes: votes, - updatedAt: data.updatedAt, - user: data.user?.name ?? '', - userImage: data.user?.image ?? '', - }; - return answerComment; - }); - }, - }) +export const questionsAnswerCommentUserRouter = createProtectedRouter() .mutation('create', { input: z.object({ answerId: z.string(), @@ -281,6 +225,5 @@ export const questionsAnswerCommentRouter = createProtectedRouter() }), ]); return answerCommentVote; - }, }); diff --git a/apps/portal/src/server/router/questions/questions-answer-router.ts b/apps/portal/src/server/router/questions/questions-answer-router.ts new file mode 100644 index 00000000..bdc5ca31 --- /dev/null +++ b/apps/portal/src/server/router/questions/questions-answer-router.ts @@ -0,0 +1,128 @@ +import { z } from 'zod'; +import { Vote } from '@prisma/client'; +import { TRPCError } from '@trpc/server'; + +import { createRouter } from '../context'; + +import type { Answer } from '~/types/questions'; + +export const questionsAnswerRouter = createRouter() + .query('getAnswers', { + input: z.object({ + questionId: z.string(), + }), + async resolve({ ctx, input }) { + const { questionId } = input; + + const answersData = await ctx.prisma.questionsAnswer.findMany({ + include: { + _count: { + select: { + comments: true, + }, + }, + user: { + select: { + image: true, + name: true, + }, + }, + votes: true, + }, + orderBy: { + createdAt: 'desc', + }, + where: { + questionId, + }, + }); + return answersData.map((data) => { + const votes: number = data.votes.reduce( + (previousValue: number, currentValue) => { + let result: number = previousValue; + + switch (currentValue.vote) { + case Vote.UPVOTE: + result += 1; + break; + case Vote.DOWNVOTE: + result -= 1; + break; + } + return result; + }, + 0, + ); + + const answer: Answer = { + content: data.content, + createdAt: data.createdAt, + id: data.id, + numComments: data._count.comments, + numVotes: votes, + user: data.user?.name ?? '', + userImage: data.user?.image ?? '', + }; + return answer; + }); + }, + }) + .query('getAnswerById', { + input: z.object({ + answerId: z.string(), + }), + async resolve({ ctx, input }) { + const answerData = await ctx.prisma.questionsAnswer.findUnique({ + include: { + _count: { + select: { + comments: true, + }, + }, + user: { + select: { + image: true, + name: true, + }, + }, + votes: true, + }, + where: { + id: input.answerId, + }, + }); + if (!answerData) { + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Answer not found', + }); + } + const votes: number = answerData.votes.reduce( + (previousValue: number, currentValue) => { + let result: number = previousValue; + + switch (currentValue.vote) { + case Vote.UPVOTE: + result += 1; + break; + case Vote.DOWNVOTE: + result -= 1; + break; + } + return result; + }, + 0, + ); + + const answer: Answer = { + content: answerData.content, + createdAt: answerData.createdAt, + id: answerData.id, + numComments: answerData._count.comments, + numVotes: votes, + user: answerData.user?.name ?? '', + userImage: answerData.user?.image ?? '', + }; + return answer; + }, + }); diff --git a/apps/portal/src/server/router/questions-answer-router.ts b/apps/portal/src/server/router/questions/questions-answer-user-router.ts similarity index 62% rename from apps/portal/src/server/router/questions-answer-router.ts rename to apps/portal/src/server/router/questions/questions-answer-user-router.ts index e2318ba7..a73f5a21 100644 --- a/apps/portal/src/server/router/questions-answer-router.ts +++ b/apps/portal/src/server/router/questions/questions-answer-user-router.ts @@ -2,130 +2,9 @@ import { z } from 'zod'; import { Vote } from '@prisma/client'; import { TRPCError } from '@trpc/server'; -import { createProtectedRouter } from './context'; +import { createProtectedRouter } from '../context'; -import type { Answer } from '~/types/questions'; - -export const questionsAnswerRouter = createProtectedRouter() - .query('getAnswers', { - input: z.object({ - questionId: z.string(), - }), - async resolve({ ctx, input }) { - const { questionId } = input; - - const answersData = await ctx.prisma.questionsAnswer.findMany({ - include: { - _count: { - select: { - comments: true, - }, - }, - user: { - select: { - image: true, - name: true, - }, - }, - votes: true, - }, - orderBy: { - createdAt: 'desc', - }, - where: { - questionId, - }, - }); - return answersData.map((data) => { - const votes: number = data.votes.reduce( - (previousValue: number, currentValue) => { - let result: number = previousValue; - - switch (currentValue.vote) { - case Vote.UPVOTE: - result += 1; - break; - case Vote.DOWNVOTE: - result -= 1; - break; - } - return result; - }, - 0, - ); - - const answer: Answer = { - content: data.content, - createdAt: data.createdAt, - id: data.id, - numComments: data._count.comments, - numVotes: votes, - user: data.user?.name ?? '', - userImage: data.user?.image ?? '', - }; - return answer; - }); - }, - }) - .query('getAnswerById', { - input: z.object({ - answerId: z.string(), - }), - async resolve({ ctx, input }) { - const answerData = await ctx.prisma.questionsAnswer.findUnique({ - include: { - _count: { - select: { - comments: true, - }, - }, - user: { - select: { - image: true, - name: true, - }, - }, - votes: true, - }, - where: { - id: input.answerId, - }, - }); - if (!answerData) { - throw new TRPCError({ - code: 'NOT_FOUND', - message: 'Answer not found', - }); - } - const votes: number = answerData.votes.reduce( - (previousValue: number, currentValue) => { - let result: number = previousValue; - - switch (currentValue.vote) { - case Vote.UPVOTE: - result += 1; - break; - case Vote.DOWNVOTE: - result -= 1; - break; - } - return result; - }, - 0, - ); - - const answer: Answer = { - content: answerData.content, - createdAt: answerData.createdAt, - id: answerData.id, - numComments: answerData._count.comments, - numVotes: votes, - user: answerData.user?.name ?? '', - userImage: answerData.user?.image ?? '', - }; - return answer; - }, - }) +export const questionsAnswerUserRouter = createProtectedRouter() .mutation('create', { input: z.object({ content: z.string(), @@ -341,6 +220,5 @@ export const questionsAnswerRouter = createProtectedRouter() }), ]); return questionsAnswerVote; - }, }); diff --git a/apps/portal/src/server/router/questions-list-crud.ts b/apps/portal/src/server/router/questions/questions-list-router.ts similarity index 92% rename from apps/portal/src/server/router/questions-list-crud.ts rename to apps/portal/src/server/router/questions/questions-list-router.ts index 1f375497..dc2d4269 100644 --- a/apps/portal/src/server/router/questions-list-crud.ts +++ b/apps/portal/src/server/router/questions/questions-list-router.ts @@ -1,9 +1,9 @@ import { z } from 'zod'; import { TRPCError } from '@trpc/server'; -import { createProtectedRouter } from './context'; +import { createProtectedRouter } from '../context'; -export const questionListRouter = createProtectedRouter() +export const questionsListRouter = createProtectedRouter() .query('getListsByUser', { async resolve({ ctx }) { const userId = ctx.session?.user?.id; @@ -14,7 +14,7 @@ export const questionListRouter = createProtectedRouter() include: { question: true, }, - } + }, }, orderBy: { createdAt: 'asc', @@ -23,7 +23,7 @@ export const questionListRouter = createProtectedRouter() id: userId, }, }); - } + }, }) .query('getListById', { input: z.object({ @@ -38,7 +38,7 @@ export const questionListRouter = createProtectedRouter() include: { question: true, }, - } + }, }, orderBy: { createdAt: 'asc', @@ -47,7 +47,7 @@ export const questionListRouter = createProtectedRouter() id: userId, }, }); - } + }, }) .mutation('create', { input: z.object({ @@ -163,11 +163,12 @@ export const questionListRouter = createProtectedRouter() async resolve({ ctx, input }) { const userId = ctx.session?.user?.id; - const entryToDelete = await ctx.prisma.questionsListQuestionEntry.findUnique({ - where: { - id: input.id, - }, - }); + const entryToDelete = + await ctx.prisma.questionsListQuestionEntry.findUnique({ + where: { + id: input.id, + }, + }); if (entryToDelete?.id !== userId) { throw new TRPCError({ @@ -176,7 +177,6 @@ export const questionListRouter = createProtectedRouter() }); } - const listToAugment = await ctx.prisma.questionsList.findUnique({ where: { id: entryToDelete.listId, diff --git a/apps/portal/src/server/router/questions/questions-question-comment-router.ts b/apps/portal/src/server/router/questions/questions-question-comment-router.ts new file mode 100644 index 00000000..1bf63789 --- /dev/null +++ b/apps/portal/src/server/router/questions/questions-question-comment-router.ts @@ -0,0 +1,64 @@ +import { z } from 'zod'; +import { Vote } from '@prisma/client'; + +import { createRouter } from '../context'; + +import type { QuestionComment } from '~/types/questions'; + +export const questionsQuestionCommentRouter = createRouter().query( + 'getQuestionComments', + { + input: z.object({ + questionId: z.string(), + }), + async resolve({ ctx, input }) { + const { questionId } = input; + const questionCommentsData = + await ctx.prisma.questionsQuestionComment.findMany({ + include: { + user: { + select: { + image: true, + name: true, + }, + }, + votes: true, + }, + orderBy: { + createdAt: 'desc', + }, + where: { + questionId, + }, + }); + return questionCommentsData.map((data) => { + const votes: number = data.votes.reduce( + (previousValue: number, currentValue) => { + let result: number = previousValue; + + switch (currentValue.vote) { + case Vote.UPVOTE: + result += 1; + break; + case Vote.DOWNVOTE: + result -= 1; + break; + } + return result; + }, + 0, + ); + + const questionComment: QuestionComment = { + content: data.content, + createdAt: data.createdAt, + id: data.id, + numVotes: votes, + user: data.user?.name ?? '', + userImage: data.user?.image ?? '', + }; + return questionComment; + }); + }, + }, +); diff --git a/apps/portal/src/server/router/questions-question-comment-router.ts b/apps/portal/src/server/router/questions/questions-question-comment-user-router.ts similarity index 76% rename from apps/portal/src/server/router/questions-question-comment-router.ts rename to apps/portal/src/server/router/questions/questions-question-comment-user-router.ts index 28cf3b9d..b216e44b 100644 --- a/apps/portal/src/server/router/questions-question-comment-router.ts +++ b/apps/portal/src/server/router/questions/questions-question-comment-user-router.ts @@ -2,65 +2,9 @@ import { z } from 'zod'; import { Vote } from '@prisma/client'; import { TRPCError } from '@trpc/server'; -import { createProtectedRouter } from './context'; +import { createProtectedRouter } from '../context'; -import type { QuestionComment } from '~/types/questions'; - -export const questionsQuestionCommentRouter = createProtectedRouter() - .query('getQuestionComments', { - input: z.object({ - questionId: z.string(), - }), - async resolve({ ctx, input }) { - const { questionId } = input; - const questionCommentsData = - await ctx.prisma.questionsQuestionComment.findMany({ - include: { - user: { - select: { - image: true, - name: true, - }, - }, - votes: true, - }, - orderBy: { - createdAt: 'desc', - }, - where: { - questionId, - }, - }); - return questionCommentsData.map((data) => { - const votes: number = data.votes.reduce( - (previousValue: number, currentValue) => { - let result: number = previousValue; - - switch (currentValue.vote) { - case Vote.UPVOTE: - result += 1; - break; - case Vote.DOWNVOTE: - result -= 1; - break; - } - return result; - }, - 0, - ); - - const questionComment: QuestionComment = { - content: data.content, - createdAt: data.createdAt, - id: data.id, - numVotes: votes, - user: data.user?.name ?? '', - userImage: data.user?.image ?? '', - }; - return questionComment; - }); - }, - }) +export const questionsQuestionCommentUserRouter = createProtectedRouter() .mutation('create', { input: z.object({ content: z.string(), @@ -168,7 +112,7 @@ export const questionsQuestionCommentRouter = createProtectedRouter() const incrementValue: number = vote === Vote.UPVOTE ? 1 : -1; - const [ questionCommentVote ] = await ctx.prisma.$transaction([ + const [questionCommentVote] = await ctx.prisma.$transaction([ ctx.prisma.questionsQuestionCommentVote.create({ data: { questionCommentId, diff --git a/apps/portal/src/server/router/questions/questions-question-encounter-router.ts b/apps/portal/src/server/router/questions/questions-question-encounter-router.ts new file mode 100644 index 00000000..31b11ab4 --- /dev/null +++ b/apps/portal/src/server/router/questions/questions-question-encounter-router.ts @@ -0,0 +1,61 @@ +import { z } from 'zod'; + +import { createRouter } from '../context'; + +import type { AggregatedQuestionEncounter } from '~/types/questions'; + +export const questionsQuestionEncounterRouter = createRouter().query( + 'getAggregatedEncounters', + { + input: z.object({ + questionId: z.string(), + }), + async resolve({ ctx, input }) { + const questionEncountersData = + await ctx.prisma.questionsQuestionEncounter.findMany({ + include: { + company: true, + }, + where: { + ...input, + }, + }); + + const companyCounts: Record = {}; + const locationCounts: Record = {}; + const roleCounts: Record = {}; + + let latestSeenAt = questionEncountersData[0].seenAt; + + for (let i = 0; i < questionEncountersData.length; i++) { + const encounter = questionEncountersData[i]; + + latestSeenAt = + latestSeenAt < encounter.seenAt ? encounter.seenAt : latestSeenAt; + + if (!(encounter.company!.name in companyCounts)) { + companyCounts[encounter.company!.name] = 1; + } + companyCounts[encounter.company!.name] += 1; + + if (!(encounter.location in locationCounts)) { + locationCounts[encounter.location] = 1; + } + locationCounts[encounter.location] += 1; + + if (!(encounter.role in roleCounts)) { + roleCounts[encounter.role] = 1; + } + roleCounts[encounter.role] += 1; + } + + const questionEncounter: AggregatedQuestionEncounter = { + companyCounts, + latestSeenAt, + locationCounts, + roleCounts, + }; + return questionEncounter; + }, + }, +); diff --git a/apps/portal/src/server/router/questions-question-encounter-router.ts b/apps/portal/src/server/router/questions/questions-question-encounter-user-router.ts similarity index 62% rename from apps/portal/src/server/router/questions-question-encounter-router.ts rename to apps/portal/src/server/router/questions/questions-question-encounter-user-router.ts index 6198d866..15a69a78 100644 --- a/apps/portal/src/server/router/questions-question-encounter-router.ts +++ b/apps/portal/src/server/router/questions/questions-question-encounter-user-router.ts @@ -1,64 +1,11 @@ import { z } from 'zod'; import { TRPCError } from '@trpc/server'; -import { createProtectedRouter } from './context'; +import { createProtectedRouter } from '../context'; -import type { AggregatedQuestionEncounter } from '~/types/questions'; import { SortOrder } from '~/types/questions.d'; - -export const questionsQuestionEncounterRouter = createProtectedRouter() - .query('getAggregatedEncounters', { - input: z.object({ - questionId: z.string(), - }), - async resolve({ ctx, input }) { - const questionEncountersData = - await ctx.prisma.questionsQuestionEncounter.findMany({ - include: { - company: true, - }, - where: { - ...input, - }, - }); - - const companyCounts: Record = {}; - const locationCounts: Record = {}; - const roleCounts: Record = {}; - - let latestSeenAt = questionEncountersData[0].seenAt; - - for (let i = 0; i < questionEncountersData.length; i++) { - const encounter = questionEncountersData[i]; - - latestSeenAt = latestSeenAt < encounter.seenAt ? encounter.seenAt : latestSeenAt; - - if (!(encounter.company!.name in companyCounts)) { - companyCounts[encounter.company!.name] = 1; - } - companyCounts[encounter.company!.name] += 1; - - if (!(encounter.location in locationCounts)) { - locationCounts[encounter.location] = 1; - } - locationCounts[encounter.location] += 1; - - if (!(encounter.role in roleCounts)) { - roleCounts[encounter.role] = 1; - } - roleCounts[encounter.role] += 1; - } - - const questionEncounter: AggregatedQuestionEncounter = { - companyCounts, - latestSeenAt, - locationCounts, - roleCounts, - }; - return questionEncounter; - }, - }) +export const questionsQuestionEncounterUserRouter = createProtectedRouter() .mutation('create', { input: z.object({ companyId: z.string(), @@ -82,10 +29,9 @@ export const questionsQuestionEncounterRouter = createProtectedRouter() ...input, userId, }, - }) + }), ]); - if (questionToUpdate === null) { throw new TRPCError({ code: 'BAD_REQUEST', @@ -93,10 +39,13 @@ export const questionsQuestionEncounterRouter = createProtectedRouter() }); } - if (!questionToUpdate.lastSeenAt || questionToUpdate.lastSeenAt < input.seenAt) { + if ( + !questionToUpdate.lastSeenAt || + questionToUpdate.lastSeenAt < input.seenAt + ) { await tx.questionsQuestion.update({ data: { - lastSeenAt : input.seenAt, + lastSeenAt: input.seenAt, }, where: { id: input.questionId, @@ -146,23 +95,23 @@ export const questionsQuestionEncounterRouter = createProtectedRouter() where: { id: input.id, }, - }) + }), ]); - if (questionToUpdate!.lastSeenAt === questionEncounterToUpdate.seenAt) { - const latestEncounter = await ctx.prisma.questionsQuestionEncounter.findFirst({ - orderBy: { - seenAt: SortOrder.DESC, - }, - where: { - questionId: questionToUpdate!.id, - }, - }); + const latestEncounter = + await ctx.prisma.questionsQuestionEncounter.findFirst({ + orderBy: { + seenAt: SortOrder.DESC, + }, + where: { + questionId: questionToUpdate!.id, + }, + }); await tx.questionsQuestion.update({ data: { - lastSeenAt : latestEncounter!.seenAt, + lastSeenAt: latestEncounter!.seenAt, }, where: { id: questionToUpdate!.id, @@ -170,10 +119,8 @@ export const questionsQuestionEncounterRouter = createProtectedRouter() }); } - return questionEncounterUpdated; }); - }, }) .mutation('delete', { @@ -208,24 +155,25 @@ export const questionsQuestionEncounterRouter = createProtectedRouter() where: { id: input.id, }, - }) + }), ]); if (questionToUpdate!.lastSeenAt === questionEncounterToDelete.seenAt) { - const latestEncounter = await ctx.prisma.questionsQuestionEncounter.findFirst({ - orderBy: { - seenAt: SortOrder.DESC, - }, - where: { - questionId: questionToUpdate!.id, - }, - }); + const latestEncounter = + await ctx.prisma.questionsQuestionEncounter.findFirst({ + orderBy: { + seenAt: SortOrder.DESC, + }, + where: { + questionId: questionToUpdate!.id, + }, + }); const lastSeenVal = latestEncounter ? latestEncounter!.seenAt : null; await tx.questionsQuestion.update({ data: { - lastSeenAt : lastSeenVal, + lastSeenAt: lastSeenVal, }, where: { id: questionToUpdate!.id, diff --git a/apps/portal/src/server/router/questions-question-router.ts b/apps/portal/src/server/router/questions/questions-question-router.ts similarity index 59% rename from apps/portal/src/server/router/questions-question-router.ts rename to apps/portal/src/server/router/questions/questions-question-router.ts index 3ea33bce..cfcd6501 100644 --- a/apps/portal/src/server/router/questions-question-router.ts +++ b/apps/portal/src/server/router/questions/questions-question-router.ts @@ -2,12 +2,12 @@ import { z } from 'zod'; import { QuestionsQuestionType, Vote } from '@prisma/client'; import { TRPCError } from '@trpc/server'; -import { createProtectedRouter } from './context'; +import { createRouter } from '../context'; import type { Question } from '~/types/questions'; import { SortOrder, SortType } from '~/types/questions.d'; -export const questionsQuestionRouter = createProtectedRouter() +export const questionsQuestionRouter = createRouter() .query('getQuestionsByFilter', { input: z.object({ companyNames: z.string().array(), @@ -315,245 +315,4 @@ export const questionsQuestionRouter = createProtectedRouter() }; return question; }, - }) - .mutation('create', { - input: z.object({ - companyId: z.string(), - content: z.string(), - location: z.string(), - questionType: z.nativeEnum(QuestionsQuestionType), - role: z.string(), - seenAt: z.date(), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - - return await ctx.prisma.questionsQuestion.create({ - data: { - content: input.content, - encounters: { - create: { - company: { - connect: { - id: input.companyId, - }, - }, - location: input.location, - role: input.role, - seenAt: input.seenAt, - user: { - connect: { - id: userId, - }, - }, - }, - }, - lastSeenAt: input.seenAt, - questionType: input.questionType, - userId, - }, - }); - }, - }) - .mutation('update', { - input: z.object({ - content: z.string().optional(), - id: z.string(), - questionType: z.nativeEnum(QuestionsQuestionType).optional(), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - - const questionToUpdate = await ctx.prisma.questionsQuestion.findUnique({ - where: { - id: input.id, - }, - }); - - if (questionToUpdate?.id !== userId) { - throw new TRPCError({ - code: 'UNAUTHORIZED', - message: 'User have no authorization to record.', - // Optional: pass the original error to retain stack trace - }); - } - - const { content, questionType } = input; - - return await ctx.prisma.questionsQuestion.update({ - data: { - content, - questionType, - }, - where: { - id: input.id, - }, - }); - }, - }) - .mutation('delete', { - input: z.object({ - id: z.string(), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - - const questionToDelete = await ctx.prisma.questionsQuestion.findUnique({ - where: { - id: input.id, - }, - }); - - if (questionToDelete?.id !== userId) { - throw new TRPCError({ - code: 'UNAUTHORIZED', - message: 'User have no authorization to record.', - // Optional: pass the original error to retain stack trace - }); - } - - return await ctx.prisma.questionsQuestion.delete({ - where: { - id: input.id, - }, - }); - }, - }) - .query('getVote', { - input: z.object({ - questionId: z.string(), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - const { questionId } = input; - - return await ctx.prisma.questionsQuestionVote.findUnique({ - where: { - questionId_userId: { questionId, userId }, - }, - }); - }, - }) - .mutation('createVote', { - input: z.object({ - questionId: z.string(), - vote: z.nativeEnum(Vote), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - const { questionId, vote } = input; - - const incrementValue = vote === Vote.UPVOTE ? 1 : -1; - - const [questionVote] = await ctx.prisma.$transaction([ - ctx.prisma.questionsQuestionVote.create({ - data: { - questionId, - userId, - vote, - }, - }), - ctx.prisma.questionsQuestion.update({ - data: { - upvotes: { - increment: incrementValue, - }, - }, - where: { - id: questionId, - }, - }), - ]); - return questionVote; - }, - }) - .mutation('updateVote', { - input: z.object({ - id: z.string(), - vote: z.nativeEnum(Vote), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - const { id, vote } = input; - - const voteToUpdate = await ctx.prisma.questionsQuestionVote.findUnique({ - where: { - id: input.id, - }, - }); - - if (voteToUpdate?.userId !== userId) { - throw new TRPCError({ - code: 'UNAUTHORIZED', - message: 'User have no authorization to record.', - }); - } - - const incrementValue = vote === Vote.UPVOTE ? 2 : -2; - - const [questionVote] = await ctx.prisma.$transaction([ - ctx.prisma.questionsQuestionVote.update({ - data: { - vote, - }, - where: { - id, - }, - }), - ctx.prisma.questionsQuestion.update({ - data: { - upvotes: { - increment: incrementValue, - }, - }, - where: { - id: voteToUpdate.questionId, - }, - }), - ]); - - return questionVote; - }, - }) - .mutation('deleteVote', { - input: z.object({ - id: z.string(), - }), - async resolve({ ctx, input }) { - const userId = ctx.session?.user?.id; - - const voteToDelete = await ctx.prisma.questionsQuestionVote.findUnique({ - where: { - id: input.id, - }, - }); - - if (voteToDelete?.userId !== userId) { - throw new TRPCError({ - code: 'UNAUTHORIZED', - message: 'User have no authorization to record.', - }); - } - - const incrementValue = voteToDelete.vote === Vote.UPVOTE ? -1 : 1; - - const [questionVote] = await ctx.prisma.$transaction([ - ctx.prisma.questionsQuestionVote.delete({ - where: { - id: input.id, - }, - }), - ctx.prisma.questionsQuestion.update({ - data: { - upvotes: { - increment: incrementValue, - }, - }, - where: { - id: voteToDelete.questionId, - }, - }), - ]); - return questionVote; - }, }); diff --git a/apps/portal/src/server/router/questions/questions-question-user-router.ts b/apps/portal/src/server/router/questions/questions-question-user-router.ts new file mode 100644 index 00000000..5a2a2c72 --- /dev/null +++ b/apps/portal/src/server/router/questions/questions-question-user-router.ts @@ -0,0 +1,248 @@ +import { z } from 'zod'; +import { QuestionsQuestionType, Vote } from '@prisma/client'; +import { TRPCError } from '@trpc/server'; + +import { createProtectedRouter } from '../context'; + +export const questionsQuestionUserRouter = createProtectedRouter() + .mutation('create', { + input: z.object({ + companyId: z.string(), + content: z.string(), + location: z.string(), + questionType: z.nativeEnum(QuestionsQuestionType), + role: z.string(), + seenAt: z.date(), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + + return await ctx.prisma.questionsQuestion.create({ + data: { + content: input.content, + encounters: { + create: { + company: { + connect: { + id: input.companyId, + }, + }, + location: input.location, + role: input.role, + seenAt: input.seenAt, + user: { + connect: { + id: userId, + }, + }, + }, + }, + lastSeenAt: input.seenAt, + questionType: input.questionType, + userId, + }, + }); + }, + }) + .mutation('update', { + input: z.object({ + content: z.string().optional(), + id: z.string(), + questionType: z.nativeEnum(QuestionsQuestionType).optional(), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + + const questionToUpdate = await ctx.prisma.questionsQuestion.findUnique({ + where: { + id: input.id, + }, + }); + + if (questionToUpdate?.id !== userId) { + throw new TRPCError({ + code: 'UNAUTHORIZED', + message: 'User have no authorization to record.', + // Optional: pass the original error to retain stack trace + }); + } + + const { content, questionType } = input; + + return await ctx.prisma.questionsQuestion.update({ + data: { + content, + questionType, + }, + where: { + id: input.id, + }, + }); + }, + }) + .mutation('delete', { + input: z.object({ + id: z.string(), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + + const questionToDelete = await ctx.prisma.questionsQuestion.findUnique({ + where: { + id: input.id, + }, + }); + + if (questionToDelete?.id !== userId) { + throw new TRPCError({ + code: 'UNAUTHORIZED', + message: 'User have no authorization to record.', + // Optional: pass the original error to retain stack trace + }); + } + + return await ctx.prisma.questionsQuestion.delete({ + where: { + id: input.id, + }, + }); + }, + }) + .query('getVote', { + input: z.object({ + questionId: z.string(), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + const { questionId } = input; + + return await ctx.prisma.questionsQuestionVote.findUnique({ + where: { + questionId_userId: { questionId, userId }, + }, + }); + }, + }) + .mutation('createVote', { + input: z.object({ + questionId: z.string(), + vote: z.nativeEnum(Vote), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + const { questionId, vote } = input; + + const incrementValue = vote === Vote.UPVOTE ? 1 : -1; + + const [questionVote] = await ctx.prisma.$transaction([ + ctx.prisma.questionsQuestionVote.create({ + data: { + questionId, + userId, + vote, + }, + }), + ctx.prisma.questionsQuestion.update({ + data: { + upvotes: { + increment: incrementValue, + }, + }, + where: { + id: questionId, + }, + }), + ]); + return questionVote; + }, + }) + .mutation('updateVote', { + input: z.object({ + id: z.string(), + vote: z.nativeEnum(Vote), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + const { id, vote } = input; + + const voteToUpdate = await ctx.prisma.questionsQuestionVote.findUnique({ + where: { + id: input.id, + }, + }); + + if (voteToUpdate?.userId !== userId) { + throw new TRPCError({ + code: 'UNAUTHORIZED', + message: 'User have no authorization to record.', + }); + } + + const incrementValue = vote === Vote.UPVOTE ? 2 : -2; + + const [questionVote] = await ctx.prisma.$transaction([ + ctx.prisma.questionsQuestionVote.update({ + data: { + vote, + }, + where: { + id, + }, + }), + ctx.prisma.questionsQuestion.update({ + data: { + upvotes: { + increment: incrementValue, + }, + }, + where: { + id: voteToUpdate.questionId, + }, + }), + ]); + + return questionVote; + }, + }) + .mutation('deleteVote', { + input: z.object({ + id: z.string(), + }), + async resolve({ ctx, input }) { + const userId = ctx.session?.user?.id; + + const voteToDelete = await ctx.prisma.questionsQuestionVote.findUnique({ + where: { + id: input.id, + }, + }); + + if (voteToDelete?.userId !== userId) { + throw new TRPCError({ + code: 'UNAUTHORIZED', + message: 'User have no authorization to record.', + }); + } + + const incrementValue = voteToDelete.vote === Vote.UPVOTE ? -1 : 1; + + const [questionVote] = await ctx.prisma.$transaction([ + ctx.prisma.questionsQuestionVote.delete({ + where: { + id: input.id, + }, + }), + ctx.prisma.questionsQuestion.update({ + data: { + upvotes: { + increment: incrementValue, + }, + }, + where: { + id: voteToDelete.questionId, + }, + }), + ]); + return questionVote; + }, + }); diff --git a/apps/portal/src/utils/offers/randomGenerator.ts b/apps/portal/src/utils/offers/randomGenerator.ts index c0a05ac9..74b10a86 100644 --- a/apps/portal/src/utils/offers/randomGenerator.ts +++ b/apps/portal/src/utils/offers/randomGenerator.ts @@ -1,9 +1,14 @@ -import type { Config} from 'unique-names-generator'; +import type { Config } from 'unique-names-generator'; import { countries, names } from 'unique-names-generator'; -import { adjectives, animals,colors, uniqueNamesGenerator } from 'unique-names-generator'; +import { + adjectives, + animals, + colors, + uniqueNamesGenerator, +} from 'unique-names-generator'; import { PrismaClient } from '@prisma/client'; -const prisma = new PrismaClient() +const prisma = new PrismaClient(); const customConfig: Config = { dictionaries: [adjectives, colors, animals], @@ -12,33 +17,34 @@ const customConfig: Config = { }; export async function generateRandomName(): Promise { - let uniqueName: string = uniqueNamesGenerator(customConfig); - - let sameNameProfiles = await prisma.offersProfile.findMany({ - where: { - profileName: uniqueName - } - }) - - while (sameNameProfiles.length !== 0) { - uniqueName = uniqueNamesGenerator(customConfig); - sameNameProfiles = await prisma.offersProfile.findMany({ - where: { - profileName: uniqueName - } - }) - } - - return uniqueName + let uniqueName: string = uniqueNamesGenerator(customConfig); + + let sameNameProfiles = await prisma.offersProfile.findMany({ + where: { + profileName: uniqueName, + }, + }); + + while (sameNameProfiles.length !== 0) { + uniqueName = uniqueNamesGenerator(customConfig); + sameNameProfiles = await prisma.offersProfile.findMany({ + where: { + profileName: uniqueName, + }, + }); + } + + return uniqueName; } const tokenConfig: Config = { - dictionaries: [adjectives, colors, animals, countries, names] - .sort((_a, _b) => 0.5 - Math.random()), + dictionaries: [adjectives, colors, animals, countries, names].sort( + (_a, _b) => 0.5 - Math.random(), + ), length: 5, separator: '-', }; export function generateRandomStringForToken(): string { - return uniqueNamesGenerator(tokenConfig) -} \ No newline at end of file + return uniqueNamesGenerator(tokenConfig); +}