[questions][feat] post, view question answers

pull/347/head
Jeff Sieu 3 years ago
parent a1925144cb
commit 6787ed117b

@ -12,6 +12,7 @@ import {
SAMPLE_QUESTION, SAMPLE_QUESTION,
} from '~/utils/questions/constants'; } from '~/utils/questions/constants';
import { useFormRegister } from '~/utils/questions/useFormRegister'; import { useFormRegister } from '~/utils/questions/useFormRegister';
import { trpc } from '~/utils/trpc';
export type AnswerCommentData = { export type AnswerCommentData = {
commentContent: string; commentContent: string;
@ -29,6 +30,14 @@ export default function QuestionPage() {
const question = SAMPLE_QUESTION; const question = SAMPLE_QUESTION;
const comment = SAMPLE_ANSWER_COMMENT; const comment = SAMPLE_ANSWER_COMMENT;
const { answerId } = router.query;
const { data: answer } = trpc.useQuery([
'questions.answers.getAnswerById',
{ answerId: answerId as string },
]);
const handleBackNavigation = () => { const handleBackNavigation = () => {
router.back(); router.back();
}; };
@ -38,6 +47,11 @@ export default function QuestionPage() {
console.log(data); console.log(data);
}; };
if (!answer) {
// TODO: Make this look nicer
return <div>Answer not found</div>;
}
return ( return (
<div className="flex w-full flex-1 items-stretch pb-4"> <div className="flex w-full flex-1 items-stretch pb-4">
<div className="flex items-baseline gap-2 py-4 pl-4"> <div className="flex items-baseline gap-2 py-4 pl-4">
@ -51,7 +65,13 @@ export default function QuestionPage() {
</div> </div>
<div className="flex w-full justify-center overflow-y-auto py-4 px-5"> <div className="flex w-full justify-center overflow-y-auto py-4 px-5">
<div className="flex max-w-7xl flex-1 flex-col gap-2"> <div className="flex max-w-7xl flex-1 flex-col gap-2">
<FullAnswerCard {...SAMPLE_ANSWER} /> <FullAnswerCard
authorImageUrl={SAMPLE_ANSWER.authorImageUrl}
authorName={answer.user}
content={answer.content}
createdAt={answer.createdAt}
upvoteCount={0}
/>
<div className="mx-2"> <div className="mx-2">
<form <form
className="mb-2" className="mb-2"

@ -11,6 +11,7 @@ import {
SAMPLE_ANSWER, SAMPLE_ANSWER,
SAMPLE_QUESTION_COMMENT, SAMPLE_QUESTION_COMMENT,
} from '~/utils/questions/constants'; } from '~/utils/questions/constants';
import createSlug from '~/utils/questions/createSlug';
import { useFormRegister } from '~/utils/questions/useFormRegister'; import { useFormRegister } from '~/utils/questions/useFormRegister';
import { trpc } from '~/utils/trpc'; import { trpc } from '~/utils/trpc';
@ -64,6 +65,17 @@ export default function QuestionPage() {
}, },
); );
const { data: answers } = trpc.useQuery([
'questions.answers.getAnswers',
{ questionId: questionId as string },
]);
const { mutate: addAnswer } = trpc.useMutation('questions.answers.create', {
onSuccess: () => {
utils.invalidateQueries('questions.answers.getAnswers');
},
});
const handleBackNavigation = () => { const handleBackNavigation = () => {
router.back(); router.back();
}; };
@ -71,6 +83,10 @@ export default function QuestionPage() {
const handleSubmitAnswer = (data: AnswerQuestionData) => { const handleSubmitAnswer = (data: AnswerQuestionData) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(data); console.log(data);
addAnswer({
content: data.answerContent,
questionId: questionId as string,
});
}; };
const handleSubmitComment = (data: QuestionCommentData) => { const handleSubmitComment = (data: QuestionCommentData) => {
@ -214,13 +230,18 @@ export default function QuestionPage() {
/> />
</div> </div>
</form> </form>
{(answers ?? []).map((answer) => (
{Array.from({ length: question.numAnswers }).map((_, index) => (
<AnswerCard <AnswerCard
// eslint-disable-next-line react/no-array-index-key key={answer.id}
key={index} authorImageUrl={SAMPLE_ANSWER.authorImageUrl}
{...SAMPLE_ANSWER} authorName={answer.user}
href={`${router.asPath}/answer/1/1`} commentCount={0}
content={answer.content}
createdAt={answer.createdAt}
href={`${router.asPath}/answer/${answer.id}/${createSlug(
answer.content,
)}`}
upvoteCount={0}
/> />
))} ))}
</div> </div>

@ -14,17 +14,17 @@ export const questionsAnswerRouter = createProtectedRouter()
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const answersData = await ctx.prisma.questionsAnswer.findMany({ const answersData = await ctx.prisma.questionsAnswer.findMany({
include: { include: {
_count: { _count: {
select: { select: {
comments: true, comments: true,
},
}, },
}, user: {
user: { select: {
select: { name: true,
name: true, },
}, },
}, votes: true,
votes: true,
}, },
orderBy: { orderBy: {
createdAt: 'desc', createdAt: 'desc',
@ -32,43 +32,93 @@ export const questionsAnswerRouter = createProtectedRouter()
where: { where: {
...input, ...input,
}, },
}); });
return answersData.map((data) => { return answersData.map((data) => {
const votes:number = data.votes.reduce( const votes: number = data.votes.reduce(
(previousValue:number, currentValue) => { (previousValue: number, currentValue) => {
let result:number = previousValue; let result: number = previousValue;
switch(currentValue.vote) {
case Vote.UPVOTE:
result += 1
break;
case Vote.DOWNVOTE:
result -= 1
break;
}
return result;
},
0
);
let userName = ""; switch (currentValue.vote) {
case Vote.UPVOTE:
result += 1;
break;
case Vote.DOWNVOTE:
result -= 1;
break;
}
return result;
},
0,
);
if (data.user) { const answer: Answer = {
userName = data.user.name!; content: data.content,
createdAt: data.createdAt,
id: data.id,
numComments: data._count.comments,
numVotes: votes,
user: data.user?.name ?? '',
};
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: {
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 = { const answer: Answer = {
content: data.content, content: answerData.content,
createdAt: data.createdAt, createdAt: answerData.createdAt,
id: data.id, id: answerData.id,
numComments: data._count.comments, numComments: answerData._count.comments,
numVotes: votes, numVotes: votes,
user: userName, user: answerData.user?.name ?? '',
}; };
return answer; return answer;
}); },
}
}) })
.mutation('create', { .mutation('create', {
input: z.object({ input: z.object({
@ -93,7 +143,7 @@ export const questionsAnswerRouter = createProtectedRouter()
}), }),
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const {content, id} = input const { content, id } = input;
const answerToUpdate = await ctx.prisma.questionsAnswer.findUnique({ const answerToUpdate = await ctx.prisma.questionsAnswer.findUnique({
where: { where: {
@ -128,7 +178,8 @@ export const questionsAnswerRouter = createProtectedRouter()
const answerToDelete = await ctx.prisma.questionsAnswer.findUnique({ const answerToDelete = await ctx.prisma.questionsAnswer.findUnique({
where: { where: {
id: input.id, id: input.id,
},}); },
});
if (answerToDelete?.id !== userId) { if (answerToDelete?.id !== userId) {
throw new TRPCError({ throw new TRPCError({
@ -150,11 +201,11 @@ export const questionsAnswerRouter = createProtectedRouter()
}), }),
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const {answerId} = input const { answerId } = input;
return await ctx.prisma.questionsAnswerVote.findUnique({ return await ctx.prisma.questionsAnswerVote.findUnique({
where: { where: {
answerId_userId : { answerId, userId }, answerId_userId: { answerId, userId },
}, },
}); });
}, },
@ -182,7 +233,7 @@ export const questionsAnswerRouter = createProtectedRouter()
}), }),
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const {id, vote} = input const { id, vote } = input;
const voteToUpdate = await ctx.prisma.questionsAnswerVote.findUnique({ const voteToUpdate = await ctx.prisma.questionsAnswerVote.findUnique({
where: { where: {
@ -217,7 +268,8 @@ export const questionsAnswerRouter = createProtectedRouter()
const voteToDelete = await ctx.prisma.questionsAnswerVote.findUnique({ const voteToDelete = await ctx.prisma.questionsAnswerVote.findUnique({
where: { where: {
id: input.id, id: input.id,
},}); },
});
if (voteToDelete?.id !== userId) { if (voteToDelete?.id !== userId) {
throw new TRPCError({ throw new TRPCError({
@ -232,4 +284,4 @@ export const questionsAnswerRouter = createProtectedRouter()
}, },
}); });
}, },
}); });

@ -47,18 +47,12 @@ export const questionsQuestionCommentRouter = createProtectedRouter()
0, 0,
); );
let userName = '';
if (data.user) {
userName = data.user.name!;
}
const questionComment: QuestionComment = { const questionComment: QuestionComment = {
content: data.content, content: data.content,
createdAt: data.createdAt, createdAt: data.createdAt,
id: data.id, id: data.id,
numVotes: votes, numVotes: votes,
user: userName, user: data.user?.name ?? '',
}; };
return questionComment; return questionComment;
}); });

@ -78,12 +78,6 @@ export const questionsQuestionRouter = createProtectedRouter()
0, 0,
); );
let userName = '';
if (data.user) {
userName = data.user.name!;
}
const question: Question = { const question: Question = {
company: data.encounters[0].company, company: data.encounters[0].company,
content: data.content, content: data.content,
@ -95,7 +89,7 @@ export const questionsQuestionRouter = createProtectedRouter()
role: data.encounters[0].role ?? 'Unknown role', role: data.encounters[0].role ?? 'Unknown role',
seenAt: data.encounters[0].seenAt, seenAt: data.encounters[0].seenAt,
updatedAt: data.updatedAt, updatedAt: data.updatedAt,
user: userName, user: data.user?.name ?? '',
}; };
return question; return question;
}); });
@ -156,12 +150,6 @@ export const questionsQuestionRouter = createProtectedRouter()
0, 0,
); );
let userName = '';
if (questionData.user) {
userName = questionData.user.name!;
}
const question: Question = { const question: Question = {
company: questionData.encounters[0].company, company: questionData.encounters[0].company,
content: questionData.content, content: questionData.content,
@ -173,7 +161,7 @@ export const questionsQuestionRouter = createProtectedRouter()
role: questionData.encounters[0].role ?? 'Unknown role', role: questionData.encounters[0].role ?? 'Unknown role',
seenAt: questionData.encounters[0].seenAt, seenAt: questionData.encounters[0].seenAt,
updatedAt: questionData.updatedAt, updatedAt: questionData.updatedAt,
user: userName, user: questionData.user?.name ?? '',
}; };
return question; return question;
}, },

@ -25,6 +25,7 @@ export type Answer = {
id: string; id: string;
numComments: number; numComments: number;
numVotes: number; numVotes: number;
user: string;
}; };
export type QuestionComment = { export type QuestionComment = {

Loading…
Cancel
Save