[questions][ui] improve browse sort ui

pull/531/head
Jeff Sieu 2 years ago
parent 2293b6b8c4
commit 964f791e46

@ -1,5 +1,4 @@
import { useState } from 'react';
import { TextInput } from '@tih/ui';
import { useProtectedCallback } from '~/utils/questions/useProtectedCallback';
@ -27,22 +26,13 @@ export default function ContributeQuestionCard({
return (
<div className="w-full">
<button
className="flex w-full flex-1 justify-between gap-2 rounded-md border border-slate-300 bg-white p-4 text-left hover:bg-slate-100"
className="flex w-full flex-1 justify-between gap-2 rounded-md border border-slate-300 bg-white p-4 text-left transition hover:bg-slate-100"
type="button"
onClick={handleOpenContribute}>
<div className="w-full">
<TextInput
disabled={true}
isLabelHidden={true}
label="Question"
placeholder="Contribute a question"
onChange={handleOpenContribute}
/>
</div>
<div className="flex flex-wrap items-end justify-start gap-2">
<h1 className="bg-primary-600 hover:bg-primary-700 rounded-full px-3 py-2 text-white">
Contribute
</h1>
<div className="w-full rounded-md border border-slate-300 bg-slate-100 py-2 px-4 text-slate-400">
<p className="font-semibold">
Just completed your interview? Contribute your questions
</p>
</div>
</button>
<ContributeQuestionDialog

@ -2,10 +2,13 @@ import {
AdjustmentsHorizontalIcon,
MagnifyingGlassIcon,
} from '@heroicons/react/24/outline';
import { Button, TextInput } from '@tih/ui';
import { Button, Tabs, TextInput } from '@tih/ui';
import { SORT_ORDERS } from '~/utils/questions/constants';
import type { SortOptionsSelectProps } from './SortOptionsSelect';
import SortOptionsSelect from './SortOptionsSelect';
import { SortOrder, SortType } from '~/types/questions.d';
export type QuestionSearchBarProps = SortOptionsSelectProps & {
onFilterOptionsToggle: () => void;
@ -13,6 +16,22 @@ export type QuestionSearchBarProps = SortOptionsSelectProps & {
query: string;
};
function getSortOrderLabel(sortOrder: SortOrder, sortType: SortType): string {
switch (sortType) {
case SortType.NEW:
return sortOrder === SortOrder.ASC ? 'Oldest first' : 'Newest first';
case SortType.TOP:
return sortOrder === SortOrder.ASC
? 'Least upvotes first'
: 'Most upvotes first';
case SortType.ENCOUNTERS:
return sortOrder === SortOrder.ASC
? 'Least received first'
: 'Most received first';
}
return '';
}
export default function QuestionSearchBar({
onFilterOptionsToggle,
onQueryChange,
@ -20,44 +39,75 @@ export default function QuestionSearchBar({
...sortOptionsSelectProps
}: QuestionSearchBarProps) {
return (
<div className="flex flex-col items-stretch gap-x-4 gap-y-4 lg:flex-row lg:items-end">
<div className="flex flex-1 gap-2">
<div className="flex-1">
<TextInput
isLabelHidden={true}
label="Search by content"
placeholder="Search by content"
startAddOn={MagnifyingGlassIcon}
startAddOnType="icon"
value={query}
onChange={(value) => {
onQueryChange(value);
}}
/>
<div className="flex flex-col gap-4">
<div className="flex flex-col items-stretch gap-x-2 gap-y-4 lg:flex-row lg:items-end">
<div className="flex flex-1 gap-2">
<div className="flex-1">
<TextInput
isLabelHidden={true}
label="Search by content"
placeholder="Search by content"
startAddOn={MagnifyingGlassIcon}
startAddOnType="icon"
value={query}
onChange={(value) => {
onQueryChange(value);
}}
/>
</div>
<div className="sm:hidden">
<Button
addonPosition="start"
icon={AdjustmentsHorizontalIcon}
isLabelHidden={true}
label="Filters"
variant="tertiary"
onClick={onFilterOptionsToggle}
/>
</div>
<div className="hidden sm:block lg:hidden">
<Button
addonPosition="start"
icon={AdjustmentsHorizontalIcon}
label="Filters"
variant="tertiary"
onClick={onFilterOptionsToggle}
/>
</div>
</div>
<div className="sm:hidden">
<Button
addonPosition="start"
icon={AdjustmentsHorizontalIcon}
isLabelHidden={true}
label="Filters"
variant="tertiary"
onClick={onFilterOptionsToggle}
{/* <SortOptionsSelect {...sortOptionsSelectProps} /> */}
</div>
<div className="flex justify-start gap-4">
<div>
<Tabs
label="Sort by"
tabs={sortOptionsSelectProps.sortTypeOptions ?? []}
value={sortOptionsSelectProps.sortTypeValue}
onChange={sortOptionsSelectProps.onSortTypeChange}
/>
</div>
<div className="hidden sm:block lg:hidden">
<Button
addonPosition="start"
icon={AdjustmentsHorizontalIcon}
label="Filters"
variant="tertiary"
onClick={onFilterOptionsToggle}
<div className="border-l" />
<div>
<Tabs
label="Order by"
tabs={(sortOptionsSelectProps.sortOrderOptions ?? SORT_ORDERS).map(
(option) => {
const newLabel = getSortOrderLabel(
option.value,
sortOptionsSelectProps.sortTypeValue,
);
return {
...option,
label: newLabel,
};
},
)}
value={sortOptionsSelectProps.sortOrderValue}
onChange={sortOptionsSelectProps.onSortOrderChange}
/>
</div>
</div>
<div className="flex items-end justify-end gap-4">
<SortOptionsSelect {...sortOptionsSelectProps} />
</div>
</div>
);
}

@ -35,7 +35,7 @@ export default function SortOptionsSelect({
const sortOrders = sortOrderOptions ?? SORT_ORDERS;
return (
<div className="flex items-end justify-end gap-4">
<div className="flex items-end justify-end gap-2">
<div className="flex items-center gap-2">
<Select
display="inline"

@ -119,7 +119,7 @@ export type BaseQuestionCardProps = ActionButtonProps &
hideCard?: boolean;
questionId: string;
showHover?: boolean;
timestamp: string | null;
timestamp: Date | null;
truncateContent?: boolean;
type: QuestionsQuestionType;
};
@ -215,7 +215,14 @@ export default function BaseQuestionCard({
<QuestionAggregateBadge statistics={roles} variant="danger" />
</>
)}
{timestamp !== null && <p className="text-xs">{timestamp}</p>}
{timestamp !== null && (
<p className="text-xs">
{timestamp.toLocaleDateString(undefined, {
month: 'short',
year: 'numeric',
})}
</p>
)}
{showAddToList && (
<div className="pl-4">
<AddToListDropdown questionId={questionId} />
@ -317,7 +324,7 @@ export default function BaseQuestionCard({
<article
className={clsx(
'group flex gap-4 border-slate-300',
showHover && 'hover:bg-slate-50',
showHover && 'transition hover:bg-slate-50',
!hideCard && 'rounded-md border bg-white p-4',
)}>
{cardContent}

@ -221,12 +221,7 @@ export default function ContributeQuestionForm({
createEncounterButtonText="Yes, this is my question"
questionId={question.id}
roles={roleCounts}
timestamp={
question.seenAt.toLocaleDateString(undefined, {
month: 'short',
year: 'numeric',
}) ?? null
}
timestamp={question.seenAt}
type={question.type}
onReceivedSubmit={async (data) => {
await addEncounterAsync({

@ -210,10 +210,7 @@ export default function QuestionPage() {
questionId={question.id}
receivedCount={undefined}
roles={relabeledAggregatedEncounters?.roleCounts ?? {}}
timestamp={question.seenAt.toLocaleDateString(undefined, {
month: 'short',
year: 'numeric',
})}
timestamp={question.seenAt}
upvoteCount={question.numVotes}
onReceivedSubmit={async (data) => {
await addEncounterAsync({

@ -558,13 +558,9 @@ export default function QuestionsBrowsePage() {
questionId={question.id}
receivedCount={question.receivedCount}
roles={roleCounts}
timestamp={question.seenAt.toLocaleDateString(
undefined,
{
month: 'short',
year: 'numeric',
},
)}
timestamp={
question.aggregatedQuestionEncounters.latestSeenAt
}
type={question.type}
upvoteCount={question.numVotes}
/>

@ -220,13 +220,7 @@ export default function ListPage() {
questionId={question.id}
receivedCount={question.receivedCount}
roles={roleCounts}
timestamp={question.seenAt.toLocaleDateString(
undefined,
{
month: 'short',
year: 'numeric',
},
)}
timestamp={question.seenAt}
type={question.type}
onDelete={() => {
deleteQuestionEntry({ id: entryId });

@ -69,38 +69,38 @@ export const QUESTION_AGES: FilterChoices<QuestionAge> = [
] as const;
export const SORT_ORDERS = [
{
label: 'Ascending',
value: SortOrder.ASC,
},
{
label: 'Descending',
value: SortOrder.DESC,
},
{
label: 'Ascending',
value: SortOrder.ASC,
},
];
export const SORT_TYPES = [
{
label: 'New',
value: SortType.NEW,
label: 'Upvotes',
value: SortType.TOP,
},
{
label: 'Top',
value: SortType.TOP,
label: 'Date',
value: SortType.NEW,
},
];
export const QUESTION_SORT_TYPES = [
{
label: 'New',
value: SortType.NEW,
label: 'Upvotes',
value: SortType.TOP,
},
{
label: 'Top',
value: SortType.TOP,
label: 'Age',
value: SortType.NEW,
},
{
label: 'Encounters',
label: 'Received',
value: SortType.ENCOUNTERS,
},
];

Loading…
Cancel
Save