[questions][feat] add homepage layout

pull/312/head
Jeff Sieu 3 years ago
parent 6c91ec2077
commit 3992504a0c

@ -0,0 +1,79 @@
import type { ComponentProps, Ref } from 'react';
import { forwardRef } from 'react';
import type { UseFormRegisterReturn } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import {
BuildingOffice2Icon,
CalendarDaysIcon,
QuestionMarkCircleIcon,
} from '@heroicons/react/24/outline';
import { Button, TextInput } from '@tih/ui';
export type ContributeQuestionData = {
company: string;
date: Date;
questionContent: string;
questionType: string;
};
type FormTextInputProps = Omit<ComponentProps<typeof TextInput>, 'onChange'> &
Pick<UseFormRegisterReturn<never>, 'onChange'>;
function FormTextInputWithRef(
props: FormTextInputProps,
ref?: Ref<HTMLInputElement>,
) {
const { onChange, ...rest } = props;
return (
<TextInput onChange={(_, event) => onChange(event)} {...rest} ref={ref} />
);
}
const FormTextInput = forwardRef(FormTextInputWithRef);
export type ContributeQuestionCardProps = {
onSubmit: (data: ContributeQuestionData) => void;
};
export default function ContributeQuestionCard({
onSubmit,
}: ContributeQuestionCardProps) {
const { register, handleSubmit } = useForm<ContributeQuestionData>();
return (
<form
className="flex flex-col items-stretch justify-center gap-2 rounded-md border border-slate-300 p-4"
onSubmit={handleSubmit(onSubmit)}>
<FormTextInput
isLabelHidden={true}
label="Question"
placeholder="Contribute a question"
{...register('questionContent')}
/>
<div className="flex items-end justify-center gap-x-2">
<div className="flex-1">
<FormTextInput
label="Company"
startIcon={BuildingOffice2Icon}
{...register('company')}
/>
</div>
<div className="flex-1">
<FormTextInput
label="Question type"
startIcon={QuestionMarkCircleIcon}
{...register('questionType')}
/>
</div>
<div className="flex-1">
<FormTextInput
label="Date"
startIcon={CalendarDaysIcon}
{...register('date')}
/>
</div>
<Button label="Contribute" type="submit" variant="primary" />
</div>
</form>
);
}

@ -0,0 +1,72 @@
import {
ChatBubbleBottomCenterTextIcon,
ChevronDownIcon,
ChevronUpIcon,
EyeIcon,
} from '@heroicons/react/24/outline';
import { Badge, Button } from '@tih/ui';
export type QuestionOverviewCardProps = {
answerCount: number;
content: string;
location: string;
role: string;
similarCount: number;
timestamp: string;
upvoteCount: number;
};
export default function QuestionOverviewCard({
answerCount,
content,
similarCount,
upvoteCount,
timestamp,
role,
location,
}: QuestionOverviewCardProps) {
return (
<article className="flex gap-2 rounded-md border border-slate-300 p-4">
<div className="flex flex-col items-center">
<Button
icon={ChevronUpIcon}
isLabelHidden={true}
label="Upvote"
variant="tertiary"
/>
<p>{upvoteCount}</p>
<Button
icon={ChevronDownIcon}
isLabelHidden={true}
label="Downvote"
variant="tertiary"
/>
</div>
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2 text-slate-500">
<Badge label="Technical" variant="primary" />
<p className="text-xs">
{timestamp} · {location} · {role}
</p>
</div>
<p className="line-clamp-2 text-ellipsis">{content}</p>
<div className="flex gap-2">
<Button
addonPosition="start"
icon={ChatBubbleBottomCenterTextIcon}
label={`${answerCount} answers`}
size="sm"
variant="tertiary"
/>
<Button
addonPosition="start"
icon={EyeIcon}
label={`${similarCount} received this`}
size="sm"
variant="tertiary"
/>
</div>
</div>
</article>
);
}

@ -0,0 +1,40 @@
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { Select, TextInput } from '@tih/ui';
export type SortOption = {
label: string;
value: string;
};
export type QuestionSearchBarProps<SortOptions extends Array<SortOption>> = {
onSortChange?: (sortValue: SortOptions[number]['value']) => void;
sortOptions: SortOptions;
sortValue: SortOptions[number]['value'];
};
export default function QuestionSearchBar<
SortOptions extends Array<SortOption>,
>({
onSortChange,
sortOptions,
sortValue,
}: QuestionSearchBarProps<SortOptions>) {
return (
<div className="flex items-end gap-2">
<div className="flex-1">
<TextInput
isLabelHidden={true}
label="Search by content"
placeholder="Search by content"
startIcon={MagnifyingGlassIcon}
/>
</div>
<Select
display="inline"
label="Sort by"
options={sortOptions}
value={sortValue}
onChange={onSortChange}></Select>
</div>
);
}

@ -1,10 +1,44 @@
import QuestionBankTitle from '~/components/questions/QuestionBankTitle';
import ContributeQuestionCard from '~/components/questions/ContributeQuestionCard';
import QuestionOverviewCard from '~/components/questions/QuestionOverviewCard';
import QuestionSearchBar from '~/components/questions/QuestionSearchBar';
export default function QuestionsHomePage() {
return (
<main className="flex-1 overflow-y-auto">
<div className="flex h-full items-center justify-center">
<QuestionBankTitle />
<main className="flex flex-1 justify-center overflow-y-auto p-4">
<div className="flex max-w-4xl flex-1 gap-x-4">
<div className="flex flex-1 flex-col items-stretch justify-start gap-4">
<ContributeQuestionCard
onSubmit={(data) => {
// eslint-disable-next-line no-console
console.log(data);
}}
/>
<QuestionSearchBar
sortOptions={[
{
label: 'Most recent',
value: 'most-recent',
},
{
label: 'Most upvotes',
value: 'most-upvotes',
},
]}
sortValue="most-recent"
/>
<QuestionOverviewCard
answerCount={0}
content="Given an array of integers nums and an integer target, return indices of the two numbers such that they add up. Given an array of integers nums and an integer target, return indices of the two numbers such that they add up. Given an array of integers nums and"
location="Menlo Park, CA"
role="Senior Engineering Manager"
similarCount={0}
timestamp=""
upvoteCount={0}
/>
</div>
<div className="flex flex-col items-center justify-center">
<h1>To do: Filter column</h1>
</div>
</div>
</main>
);

Loading…
Cancel
Save