mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2026-04-01 18:10:34 +08:00
[questions][refactor] tweak browse page
This commit is contained in:
@@ -21,6 +21,7 @@ export default function PaginationLoadMoreButton(
|
||||
return (
|
||||
<Button
|
||||
disabled={!hasNextPage || isFetchingNextPage}
|
||||
display="block"
|
||||
isLoading={isFetchingNextPage}
|
||||
label={hasNextPage ? 'Load more' : 'Nothing more to load'}
|
||||
variant="tertiary"
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
AdjustmentsHorizontalIcon,
|
||||
MagnifyingGlassIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { Button, Tabs, TextInput } from '@tih/ui';
|
||||
import { Button, DropdownMenu, TextInput } from '@tih/ui';
|
||||
|
||||
import { SORT_ORDERS } from '~/utils/questions/constants';
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function QuestionSearchBar({
|
||||
return (
|
||||
<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 flex-1 items-center gap-4">
|
||||
<div className="flex-1">
|
||||
<TextInput
|
||||
isLabelHidden={true}
|
||||
@@ -57,52 +57,48 @@ export default function QuestionSearchBar({
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<DropdownMenu align="end" label="Sort by">
|
||||
{(sortOptionsSelectProps.sortTypeOptions ?? []).map(
|
||||
({ value: sortTypeValue }) =>
|
||||
(sortOptionsSelectProps?.sortOrderOptions ?? SORT_ORDERS).map(
|
||||
({ value: sortOrderValue }) => (
|
||||
<DropdownMenu.Item
|
||||
key={`${sortTypeValue}/${sortOrderValue}`}
|
||||
isSelected={
|
||||
sortOptionsSelectProps.sortTypeValue ===
|
||||
sortTypeValue &&
|
||||
sortOptionsSelectProps.sortOrderValue === sortOrderValue
|
||||
}
|
||||
label={getSortOrderLabel(sortOrderValue, sortTypeValue)}
|
||||
onClick={() => {
|
||||
sortOptionsSelectProps.onSortTypeChange?.(
|
||||
sortTypeValue,
|
||||
);
|
||||
sortOptionsSelectProps.onSortOrderChange?.(
|
||||
sortOrderValue,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
),
|
||||
)}
|
||||
</DropdownMenu>
|
||||
<div className="lg:hidden">
|
||||
<Button
|
||||
addonPosition="start"
|
||||
icon={AdjustmentsHorizontalIcon}
|
||||
label={
|
||||
aria-label={
|
||||
activeFilterCount > 0
|
||||
? `Filters (${activeFilterCount})`
|
||||
: 'Filters'
|
||||
}
|
||||
icon={AdjustmentsHorizontalIcon}
|
||||
label={`(${activeFilterCount})`}
|
||||
variant={activeFilterCount > 0 ? 'secondary' : 'tertiary'}
|
||||
onClick={onFilterOptionsToggle}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col justify-start gap-x-4 gap-y-2 sm:flex-row">
|
||||
<div>
|
||||
<Tabs
|
||||
label="Sort by"
|
||||
tabs={sortOptionsSelectProps.sortTypeOptions ?? []}
|
||||
value={sortOptionsSelectProps.sortTypeValue}
|
||||
onChange={sortOptionsSelectProps.onSortTypeChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="border-b 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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import QuestionSearchBar from '~/components/questions/QuestionSearchBar';
|
||||
import CompanyTypeahead from '~/components/questions/typeahead/CompanyTypeahead';
|
||||
import LocationTypeahead from '~/components/questions/typeahead/LocationTypeahead';
|
||||
import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead';
|
||||
import Container from '~/components/shared/Container';
|
||||
import type { JobTitleType } from '~/components/shared/JobTitles';
|
||||
import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
|
||||
|
||||
@@ -504,10 +505,10 @@ export default function QuestionsBrowsePage() {
|
||||
<Head>
|
||||
<title>Home - {APP_TITLE}</title>
|
||||
</Head>
|
||||
<main className="flex h-[calc(100vh_-_64px)] flex-1 flex-col items-stretch">
|
||||
<div className="flex h-full flex-1">
|
||||
<main>
|
||||
<Container className="relative flex" variant="sm">
|
||||
<section className="min-h-0 flex-1 overflow-auto">
|
||||
<div className="my-4 mx-auto flex max-w-3xl flex-col items-stretch justify-start gap-6 p-4">
|
||||
<div className="my-4 mx-auto flex flex-col items-stretch justify-start gap-6 sm:px-4">
|
||||
<ContributeQuestionCard
|
||||
onSubmit={(data) => {
|
||||
const { cityId, countryId, stateId } = data.location;
|
||||
@@ -584,22 +585,22 @@ export default function QuestionsBrowsePage() {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<aside className="hidden w-[300px] overflow-y-auto border-l bg-white py-4 lg:block">
|
||||
<aside className="sticky top-16 hidden h-[calc(100vh-4rem)] w-[300px] overflow-y-auto border-x bg-white py-4 lg:block">
|
||||
<h2 className="px-4 text-xl font-semibold">Filter by</h2>
|
||||
{filterSidebar}
|
||||
</aside>
|
||||
<SlideOut
|
||||
className="lg:hidden"
|
||||
enterFrom="end"
|
||||
isShown={filterDrawerOpen}
|
||||
size="sm"
|
||||
title="Filter by"
|
||||
onClose={() => {
|
||||
setFilterDrawerOpen(false);
|
||||
}}>
|
||||
{filterSidebar}
|
||||
</SlideOut>
|
||||
</div>
|
||||
</Container>
|
||||
<SlideOut
|
||||
className="lg:hidden"
|
||||
enterFrom="end"
|
||||
isShown={filterDrawerOpen}
|
||||
size="sm"
|
||||
title="Filter by"
|
||||
onClose={() => {
|
||||
setFilterDrawerOpen(false);
|
||||
}}>
|
||||
{filterSidebar}
|
||||
</SlideOut>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user