[questions][feat] view, post answer comments

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

@ -9,7 +9,6 @@ import CommentListItem from '~/components/questions/CommentListItem';
import { import {
SAMPLE_ANSWER, SAMPLE_ANSWER,
SAMPLE_ANSWER_COMMENT, SAMPLE_ANSWER_COMMENT,
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'; import { trpc } from '~/utils/trpc';
@ -23,28 +22,48 @@ export default function QuestionPage() {
const { const {
register: comRegister, register: comRegister,
reset: resetComment,
handleSubmit: handleCommentSubmit, handleSubmit: handleCommentSubmit,
formState: { isDirty: isCommentDirty, isValid: isCommentValid }, formState: { isDirty: isCommentDirty, isValid: isCommentValid },
} = useForm<AnswerCommentData>({ mode: 'onChange' }); } = useForm<AnswerCommentData>({ mode: 'onChange' });
const commentRegister = useFormRegister(comRegister); const commentRegister = useFormRegister(comRegister);
const question = SAMPLE_QUESTION;
const comment = SAMPLE_ANSWER_COMMENT;
const { answerId } = router.query; const { answerId } = router.query;
const utils = trpc.useContext();
const { data: answer } = trpc.useQuery([ const { data: answer } = trpc.useQuery([
'questions.answers.getAnswerById', 'questions.answers.getAnswerById',
{ answerId: answerId as string }, { answerId: answerId as string },
]); ]);
const { data: comments } = trpc.useQuery([
'questions.answers.comments.getAnswerComments',
{ answerId: answerId as string },
]);
const { mutate: addComment } = trpc.useMutation(
'questions.answers.comments.create',
{
onSuccess: () => {
utils.invalidateQuery([
'questions.answers.comments.getAnswerComments',
{ answerId: answerId as string },
]);
},
},
);
const handleBackNavigation = () => { const handleBackNavigation = () => {
router.back(); router.back();
}; };
const handleSubmitComment = (data: AnswerCommentData) => { const handleSubmitComment = (data: AnswerCommentData) => {
// eslint-disable-next-line no-console resetComment();
console.log(data); addComment({
answerId: answerId as string,
content: data.commentContent,
});
}; };
if (!answer) { if (!answer) {
@ -109,7 +128,8 @@ export default function QuestionPage() {
onChange={(value) => { onChange={(value) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(value); console.log(value);
}}></Select> }}
/>
</div> </div>
<Button <Button
@ -121,11 +141,14 @@ export default function QuestionPage() {
</div> </div>
</form> </form>
{Array.from({ length: question.commentCount }).map((_, index) => ( {(comments ?? []).map((comment) => (
<CommentListItem <CommentListItem
// eslint-disable-next-line react/no-array-index-key key={comment.id}
key={index} authorImageUrl={SAMPLE_ANSWER_COMMENT.authorImageUrl}
{...comment} authorName={comment.user}
content={comment.content}
createdAt={comment.createdAt}
upvoteCount={comment.numVotes}
/> />
))} ))}
</div> </div>

@ -81,8 +81,6 @@ export default function QuestionPage() {
}; };
const handleSubmitAnswer = (data: AnswerQuestionData) => { const handleSubmitAnswer = (data: AnswerQuestionData) => {
// eslint-disable-next-line no-console
console.log(data);
addAnswer({ addAnswer({
content: data.answerContent, content: data.answerContent,
questionId: questionId as string, questionId: questionId as string,
@ -98,7 +96,11 @@ export default function QuestionPage() {
}; };
if (!question) { if (!question) {
return <Spinner size="lg" />; return (
<div className="flex h-full w-full items-center justify-center">
<Spinner size="lg" />
</div>
);
} }
return ( return (
@ -159,7 +161,8 @@ export default function QuestionPage() {
onChange={(value) => { onChange={(value) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(value); console.log(value);
}}></Select> }}
/>
</div> </div>
<Button <Button
@ -219,7 +222,8 @@ export default function QuestionPage() {
onChange={(value) => { onChange={(value) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(value); console.log(value);
}}></Select> }}
/>
</div> </div>
</div> </div>
<Button <Button
@ -235,13 +239,13 @@ export default function QuestionPage() {
key={answer.id} key={answer.id}
authorImageUrl={SAMPLE_ANSWER.authorImageUrl} authorImageUrl={SAMPLE_ANSWER.authorImageUrl}
authorName={answer.user} authorName={answer.user}
commentCount={0} commentCount={answer.numComments}
content={answer.content} content={answer.content}
createdAt={answer.createdAt} createdAt={answer.createdAt}
href={`${router.asPath}/answer/${answer.id}/${createSlug( href={`${router.asPath}/answer/${answer.id}/${createSlug(
answer.content, answer.content,
)}`} )}`}
upvoteCount={0} upvoteCount={answer.numVotes}
/> />
))} ))}
</div> </div>

@ -12,57 +12,52 @@ export const questionsAnswerCommentRouter = createProtectedRouter()
answerId: z.string(), answerId: z.string(),
}), }),
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const questionAnswerCommentsData = await ctx.prisma.questionsAnswerComment.findMany({ const questionAnswerCommentsData =
include: { await ctx.prisma.questionsAnswerComment.findMany({
user: { include: {
select: { user: {
name: true, select: {
name: true,
},
},
votes: true,
}, },
}, orderBy: {
votes: true, createdAt: 'desc',
}, },
orderBy: { where: {
createdAt: 'desc', ...input,
}, },
where: { });
...input, return questionAnswerCommentsData.map((data) => {
}, const votes: number = data.votes.reduce(
}); (previousValue: number, currentValue) => {
return questionAnswerCommentsData.map((data) => { let result: number = previousValue;
const votes:number = data.votes.reduce(
(previousValue:number, currentValue) => { switch (currentValue.vote) {
let result:number = previousValue; case Vote.UPVOTE:
result += 1;
switch(currentValue.vote) { break;
case Vote.UPVOTE: case Vote.DOWNVOTE:
result += 1 result -= 1;
break; break;
case Vote.DOWNVOTE: }
result -= 1 return result;
break; },
} 0,
return result;
},
0
); );
let userName = ""; const answerComment: AnswerComment = {
content: data.content,
if (data.user) { createdAt: data.createdAt,
userName = data.user.name!; id: data.id,
} numVotes: votes,
updatedAt: data.updatedAt,
user: data.user?.name ?? '',
const answerComment: AnswerComment = { };
content: data.content, return answerComment;
id: data.id, });
numVotes: votes, },
updatedAt: data.updatedAt,
user: userName,
};
return answerComment;
});
}
}) })
.mutation('create', { .mutation('create', {
input: z.object({ input: z.object({
@ -88,11 +83,12 @@ export const questionsAnswerCommentRouter = createProtectedRouter()
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const answerCommentToUpdate = await ctx.prisma.questionsAnswerComment.findUnique({ const answerCommentToUpdate =
where: { await ctx.prisma.questionsAnswerComment.findUnique({
id: input.id, where: {
}, id: input.id,
}); },
});
if (answerCommentToUpdate?.id !== userId) { if (answerCommentToUpdate?.id !== userId) {
throw new TRPCError({ throw new TRPCError({
@ -118,11 +114,12 @@ export const questionsAnswerCommentRouter = createProtectedRouter()
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const answerCommentToDelete = await ctx.prisma.questionsAnswerComment.findUnique({ const answerCommentToDelete =
where: { await ctx.prisma.questionsAnswerComment.findUnique({
id: input.id, where: {
}, id: input.id,
}); },
});
if (answerCommentToDelete?.id !== userId) { if (answerCommentToDelete?.id !== userId) {
throw new TRPCError({ throw new TRPCError({
@ -144,11 +141,11 @@ export const questionsAnswerCommentRouter = createProtectedRouter()
}), }),
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const {answerCommentId} = input const { answerCommentId } = input;
return await ctx.prisma.questionsAnswerCommentVote.findUnique({ return await ctx.prisma.questionsAnswerCommentVote.findUnique({
where: { where: {
answerCommentId_userId : {answerCommentId,userId }, answerCommentId_userId: { answerCommentId, userId },
}, },
}); });
}, },
@ -176,13 +173,14 @@ export const questionsAnswerCommentRouter = 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.questionsAnswerCommentVote.findUnique({ const voteToUpdate =
where: { await ctx.prisma.questionsAnswerCommentVote.findUnique({
id: input.id, where: {
}, id: input.id,
}); },
});
if (voteToUpdate?.id !== userId) { if (voteToUpdate?.id !== userId) {
throw new TRPCError({ throw new TRPCError({
@ -208,10 +206,12 @@ export const questionsAnswerCommentRouter = createProtectedRouter()
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id; const userId = ctx.session?.user?.id;
const voteToDelete = await ctx.prisma.questionsAnswerCommentVote.findUnique({ const voteToDelete =
where: { await ctx.prisma.questionsAnswerCommentVote.findUnique({
id: input.id, where: {
},}); id: input.id,
},
});
if (voteToDelete?.id !== userId) { if (voteToDelete?.id !== userId) {
throw new TRPCError({ throw new TRPCError({
@ -226,4 +226,4 @@ export const questionsAnswerCommentRouter = createProtectedRouter()
}, },
}); });
}, },
}); });

@ -15,8 +15,11 @@ export type Question = {
export type AnswerComment = { export type AnswerComment = {
content: string; content: string;
createdAt: Date;
id: string; id: string;
numVotes: number; numVotes: number;
updatedAt: Date;
user: string;
}; };
export type Answer = { export type Answer = {

Loading…
Cancel
Save