[questions][ui] add comments & commments page

pull/346/head
wlren 3 years ago
parent 2680f7fec6
commit 685f5483f6

@ -0,0 +1,38 @@
import { format } from 'date-fns';
import VotingButtons from './VotingButtons';
export type CommentListItemProps = {
authorImageUrl: string;
authorName: string;
content: string;
createdAt: Date;
upvoteCount: number;
};
export default function CommentListItem({
authorImageUrl,
authorName,
content,
createdAt,
upvoteCount,
}: CommentListItemProps) {
return (
<div className="flex gap-4 border bg-white p-2 ">
<VotingButtons size="sm" upvoteCount={upvoteCount} />
<div className="mt-1 flex flex-col gap-1">
<div className="flex items-center gap-2">
<img
alt={`${authorName} profile picture`}
className="h-8 w-8 rounded-full"
src={authorImageUrl}></img>
<h1 className="font-bold">{authorName}</h1>
<p className="pt-1 text-xs font-extralight">
Posted on: {format(createdAt, 'Pp')}
</p>
</div>
<p className="pl-1 pt-1">{content}</p>
</div>
</div>
);
}

@ -0,0 +1,38 @@
import { format } from 'date-fns';
import VotingButtons from '../VotingButtons';
export type FullAnswerCardProps = {
authorImageUrl: string;
authorName: string;
content: string;
createdAt: Date;
upvoteCount: number;
};
export default function FullAnswerCard({
authorImageUrl,
authorName,
content,
createdAt,
upvoteCount,
}: FullAnswerCardProps) {
return (
<article className="flex gap-4 rounded-md border border-slate-300 bg-white p-4">
<VotingButtons upvoteCount={upvoteCount}></VotingButtons>
<div className="mt-1 flex flex-col gap-1">
<div className="flex items-center gap-2">
<img
alt={`${authorName} profile picture`}
className="h-8 w-8 rounded-full"
src={authorImageUrl}></img>
<h1 className="font-bold">{authorName}</h1>
<p className="pt-1 text-xs font-extralight">
Posted on: {format(createdAt, 'Pp')}
</p>
</div>
<p className="pl-1 pt-1">{content}</p>
</div>
</article>
);
}

@ -1,39 +1,45 @@
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { ArrowSmallLeftIcon } from '@heroicons/react/24/outline'; import { ArrowSmallLeftIcon } from '@heroicons/react/24/outline';
import { Button, Collapsible, Select, TextArea } from '@tih/ui'; import { Button, Select, TextArea } from '@tih/ui';
import AnswerCard from '~/components/questions/card/AnswerCard'; import FullAnswerCard from '~/components/questions/card/FullAnswerCard';
import FullQuestionCard from '~/components/questions/card/FullQuestionCard'; import CommentListItem from '~/components/questions/CommentListItem';
import { SAMPLE_QUESTION } from '~/utils/questions/constants'; import {
SAMPLE_ANSWER,
SAMPLE_ANSWER_COMMENT,
SAMPLE_QUESTION,
} from '~/utils/questions/constants';
import { useFormRegister } from '~/utils/questions/useFormRegister'; import { useFormRegister } from '~/utils/questions/useFormRegister';
export type AnswerData = { export type AnswerCommentData = {
answerContent: string; commentContent: string;
}; };
export default function QuestionPage() { export default function QuestionPage() {
const router = useRouter(); const router = useRouter();
const { const {
register: formRegister, register: comRegister,
handleSubmit, handleSubmit: handleCommentSubmit,
formState: { isDirty, isValid }, formState: { isDirty: isCommentDirty, isValid: isCommentValid },
} = useForm<AnswerData>({ mode: 'onChange' }); } = useForm<AnswerCommentData>({ mode: 'onChange' });
const register = useFormRegister(formRegister); const commentRegister = useFormRegister(comRegister);
const question = SAMPLE_QUESTION;
const question = SAMPLE_QUESTION;
const comment = SAMPLE_ANSWER_COMMENT;
const handleBackNavigation = () => { const handleBackNavigation = () => {
router.back(); router.back();
}; };
const handleSubmitAnswer = (data: AnswerData) => { const handleSubmitComment = (data: AnswerCommentData) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(data); console.log(data);
}; };
return ( return (
<div className="flex"> <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">
<Button <Button
addonPosition="start" addonPosition="start"
@ -43,33 +49,24 @@ export default function QuestionPage() {
variant="secondary" variant="secondary"
onClick={handleBackNavigation}></Button> onClick={handleBackNavigation}></Button>
</div> </div>
<div className="flex flex-col items-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-col gap-2"> <div className="flex max-w-7xl flex-1 flex-col gap-2">
<FullQuestionCard {...question} showVoteButtons={true} /> <FullAnswerCard {...SAMPLE_ANSWER} />
<div className="mx-2"> <div className="mx-2">
<Collapsible label="256 comments"> <form
<div>Comment placeholder</div> className="mb-2"
</Collapsible> onSubmit={handleCommentSubmit(handleSubmitComment)}>
</div>
<form onSubmit={handleSubmit(handleSubmitAnswer)}>
<TextArea <TextArea
{...register('answerContent', { minLength: 1, required: true })} {...commentRegister('commentContent', {
label="Contribute your answer" minLength: 1,
required: true,
})}
label="Post a comment"
required={true} required={true}
resize="vertical" resize="vertical"
rows={5} rows={2}
/> />
<div className="mt-2 flex justify-end"> <div className="my-3 flex justify-between">
<Button
disabled={!isDirty || !isValid}
label="Contribute"
type="submit"
variant="primary"
/>
</div>
</form>
<div className="my-2 flex items-baseline justify-between">
<p>{question.answerCount} answers</p>
<div className="flex items-baseline gap-2"> <div className="flex items-baseline gap-2">
<span aria-hidden={true} className="text-sm"> <span aria-hidden={true} className="text-sm">
Sort by: Sort by:
@ -94,22 +91,26 @@ export default function QuestionPage() {
console.log(value); console.log(value);
}}></Select> }}></Select>
</div> </div>
<Button
disabled={!isCommentDirty || !isCommentValid}
label="Post"
type="submit"
variant="primary"
/>
</div> </div>
</form>
{Array.from({ length: question.answerCount }).map((_, index) => ( {Array.from({ length: question.commentCount }).map((_, index) => (
<AnswerCard <CommentListItem
// eslint-disable-next-line react/no-array-index-key // eslint-disable-next-line react/no-array-index-key
key={index} key={index}
authorImageUrl="https://avatars.githubusercontent.com/u/66356390?v=4" {...comment}
authorName="James Smith"
content="Hello"
createdAt={new Date()}
href={`${router.asPath}/answer/1/1`}
upvoteCount={10}
/> />
))} ))}
</div> </div>
</div> </div>
</div> </div>
</div>
); );
} }

@ -5,24 +5,41 @@ import { Button, Collapsible, Select, TextArea } from '@tih/ui';
import AnswerCard from '~/components/questions/card/AnswerCard'; import AnswerCard from '~/components/questions/card/AnswerCard';
import FullQuestionCard from '~/components/questions/card/FullQuestionCard'; import FullQuestionCard from '~/components/questions/card/FullQuestionCard';
import CommentListItem from '~/components/questions/CommentListItem';
import { SAMPLE_QUESTION } from '~/utils/questions/constants'; import {
SAMPLE_ANSWER,
SAMPLE_QUESTION,
SAMPLE_QUESTION_COMMENT,
} from '~/utils/questions/constants';
import { useFormRegister } from '~/utils/questions/useFormRegister'; import { useFormRegister } from '~/utils/questions/useFormRegister';
export type AnswerQuestionData = { export type AnswerQuestionData = {
answerContent: string; answerContent: string;
}; };
export type QuestionCommentData = {
commentContent: string;
};
export default function QuestionPage() { export default function QuestionPage() {
const router = useRouter(); const router = useRouter();
const { const {
register: formRegister, register: ansRegister,
handleSubmit, handleSubmit,
formState: { isDirty, isValid }, formState: { isDirty, isValid },
} = useForm<AnswerQuestionData>({ mode: 'onChange' }); } = useForm<AnswerQuestionData>({ mode: 'onChange' });
const register = useFormRegister(formRegister); const answerRegister = useFormRegister(ansRegister);
const question = SAMPLE_QUESTION;
const {
register: comRegister,
handleSubmit: handleCommentSubmit,
formState: { isDirty: isCommentDirty, isValid: isCommentValid },
} = useForm<QuestionCommentData>({ mode: 'onChange' });
const commentRegister = useFormRegister(comRegister);
const question = SAMPLE_QUESTION;
const comment = SAMPLE_QUESTION_COMMENT;
const handleBackNavigation = () => { const handleBackNavigation = () => {
router.back(); router.back();
}; };
@ -32,8 +49,13 @@ export default function QuestionPage() {
console.log(data); console.log(data);
}; };
const handleSubmitComment = (data: QuestionCommentData) => {
// eslint-disable-next-line no-console
console.log(data);
};
return ( return (
<div className="flex"> <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">
<Button <Button
addonPosition="start" addonPosition="start"
@ -43,32 +65,81 @@ export default function QuestionPage() {
variant="secondary" variant="secondary"
onClick={handleBackNavigation}></Button> onClick={handleBackNavigation}></Button>
</div> </div>
<div className="flex flex-col items-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-col gap-2"> <div className="flex max-w-7xl flex-1 flex-col gap-2">
<FullQuestionCard {...question} showVoteButtons={true} /> <FullQuestionCard {...question} showVoteButtons={true} />
<div className="mx-2"> <div className="mx-2">
<Collapsible label="256 comments"> <Collapsible label={`${question.commentCount} comment(s)`}>
<div>Comment placeholder</div> <form
</Collapsible> className="mb-2"
</div> onSubmit={handleCommentSubmit(handleSubmitComment)}>
<form onSubmit={handleSubmit(handleSubmitAnswer)}>
<TextArea <TextArea
{...register('answerContent', { minLength: 1, required: true })} {...commentRegister('commentContent', {
label="Contribute your answer" minLength: 1,
required: true,
})}
label="Post a comment"
required={true} required={true}
resize="vertical" resize="vertical"
rows={5} rows={2}
/> />
<div className="mt-2 flex justify-end"> <div className="my-3 flex justify-between">
<div className="flex items-baseline gap-2">
<span aria-hidden={true} className="text-sm">
Sort by:
</span>
<Select
display="inline"
isLabelHidden={true}
label="Sort by"
options={[
{
label: 'Most recent',
value: 'most-recent',
},
{
label: 'Most upvotes',
value: 'most-upvotes',
},
]}
value="most-recent"
onChange={(value) => {
// eslint-disable-next-line no-console
console.log(value);
}}></Select>
</div>
<Button <Button
disabled={!isDirty || !isValid} disabled={!isCommentDirty || !isCommentValid}
label="Contribute" label="Post"
type="submit" type="submit"
variant="primary" variant="primary"
/> />
</div> </div>
</form> </form>
<div className="my-2 flex items-baseline justify-between">
{Array.from({ length: question.commentCount }).map((_, index) => (
<CommentListItem
// eslint-disable-next-line react/no-array-index-key
key={index}
{...comment}
/>
))}
</Collapsible>
</div>
<form onSubmit={handleSubmit(handleSubmitAnswer)}>
<TextArea
{...answerRegister('answerContent', {
minLength: 1,
required: true,
})}
label="Contribute your answer"
required={true}
resize="vertical"
rows={5}
/>
<div className="mt-3 mb-1 flex justify-between">
<div className="flex items-baseline justify-start gap-2">
<p>{question.answerCount} answers</p> <p>{question.answerCount} answers</p>
<div className="flex items-baseline gap-2"> <div className="flex items-baseline gap-2">
<span aria-hidden={true} className="text-sm"> <span aria-hidden={true} className="text-sm">
@ -95,17 +166,21 @@ export default function QuestionPage() {
}}></Select> }}></Select>
</div> </div>
</div> </div>
<Button
disabled={!isDirty || !isValid}
label="Contribute"
type="submit"
variant="primary"
/>
</div>
</form>
{Array.from({ length: question.answerCount }).map((_, index) => ( {Array.from({ length: question.answerCount }).map((_, index) => (
<AnswerCard <AnswerCard
// eslint-disable-next-line react/no-array-index-key // eslint-disable-next-line react/no-array-index-key
key={index} key={index}
authorImageUrl="https://avatars.githubusercontent.com/u/66356390?v=4" {...SAMPLE_ANSWER}
authorName="James Smith"
content="Hello"
createdAt={new Date()}
href={`${router.asPath}/answer/1/1`} href={`${router.asPath}/answer/1/1`}
upvoteCount={10}
/> />
))} ))}
</div> </div>

Loading…
Cancel
Save