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>
|
||||
);
|
||||
}
|
Loading…
Reference in new issue