[offers][refactor] improve offers table responsiveness

pull/492/head
Yangshun Tay 2 years ago
parent ab7f064734
commit 55e93102de

@ -7,7 +7,7 @@ import OffersTablePagination from '~/components/offers/table/OffersTablePaginati
import {
OfferTableFilterOptions,
OfferTableSortBy,
OfferTableTabOptions,
OfferTableYoeOptions,
YOE_CATEGORY,
} from '~/components/offers/table/types';
@ -29,7 +29,7 @@ export default function OffersTable({
jobTitleFilter,
}: OffersTableProps) {
const [currency, setCurrency] = useState(Currency.SGD.toString()); // TODO: Detect location
const [selectedTab, setSelectedTab] = useState(YOE_CATEGORY.ENTRY);
const [selectedYoe, setSelectedYoe] = useState(YOE_CATEGORY.ENTRY);
const [pagination, setPagination] = useState<Paging>({
currentPage: 0,
numOfItems: 0,
@ -48,7 +48,7 @@ export default function OffersTable({
numOfPages: 0,
totalItems: 0,
});
}, [selectedTab, currency]);
}, [selectedYoe, currency]);
const offersQuery = trpc.useQuery(
[
'offers.list',
@ -60,7 +60,7 @@ export default function OffersTable({
offset: pagination.currentPage,
sortBy: OfferTableSortBy[selectedFilter] ?? '-monthYearReceived',
title: jobTitleFilter,
yoeCategory: selectedTab,
yoeCategory: selectedYoe,
},
],
{
@ -76,22 +76,15 @@ export default function OffersTable({
function renderFilters() {
return (
<div className="m-4 flex grid grid-cols-1 items-center justify-between gap-6 sm:grid-cols-4">
<DropdownMenu
align="start"
label={
OfferTableTabOptions.filter(
({ value: itemValue }) => itemValue === selectedTab,
)[0].label
}
size="inherit">
{OfferTableTabOptions.map(({ label: itemLabel, value }) => (
<div className="flex items-center justify-between p-4 text-sm sm:grid-cols-4 md:text-base">
<DropdownMenu align="start" label="Filters" size="inherit">
{OfferTableYoeOptions.map(({ label: itemLabel, value }) => (
<DropdownMenu.Item
key={value}
isSelected={value === selectedTab}
isSelected={value === selectedYoe}
label={itemLabel}
onClick={() => {
setSelectedTab(value);
setSelectedYoe(value);
gaEvent({
action: `offers.table_filter_yoe_category_${value}`,
category: 'engagement',
@ -103,7 +96,9 @@ export default function OffersTable({
</DropdownMenu>
<div className="divide-x-slate-200 col-span-3 flex items-center justify-end space-x-4 divide-x">
<div className="justify-left flex items-center space-x-2">
<span>View all offers in</span>
<span className="sr-only sm:not-sr-only sm:inline">
View all offers in
</span>
<CurrencySelector
handleCurrencyChange={(value: string) => setCurrency(value)}
selectedCurrency={currency}
@ -140,7 +135,7 @@ export default function OffersTable({
'Company',
'Title',
'YOE',
selectedTab === YOE_CATEGORY.INTERN ? 'Monthly Salary' : 'Annual TC',
selectedYoe === YOE_CATEGORY.INTERN ? 'Monthly Salary' : 'Annual TC',
'Date Offered',
'Actions',
];
@ -172,34 +167,32 @@ export default function OffersTable({
};
return (
<div className="w-5/6">
<div className="relative w-full border border-slate-200">
{renderFilters()}
{offersQuery.isLoading ? (
<div className="col-span-10 pt-4">
<Spinner display="block" size="lg" />
</div>
) : (
<div className="overflow-x-auto">
<table className="w-full divide-y divide-slate-200 border-y border-slate-200 text-left text-slate-600">
{renderHeader()}
<tbody>
{offers.map((offer) => (
<OffersRow key={offer.id} row={offer} />
))}
</tbody>
</table>
</div>
)}
<OffersTablePagination
endNumber={
pagination.currentPage * NUMBER_OF_OFFERS_IN_PAGE + offers.length
}
handlePageChange={handlePageChange}
pagination={pagination}
startNumber={pagination.currentPage * NUMBER_OF_OFFERS_IN_PAGE + 1}
/>
</div>
<div className="relative w-full border border-slate-200">
{renderFilters()}
{offersQuery.isLoading ? (
<div className="col-span-10 pt-4">
<Spinner display="block" size="lg" />
</div>
) : (
<div className="overflow-x-auto">
<table className="w-full divide-y divide-slate-200 border-y border-slate-200 text-left text-slate-600">
{renderHeader()}
<tbody>
{offers.map((offer) => (
<OffersRow key={offer.id} row={offer} />
))}
</tbody>
</table>
</div>
)}
<OffersTablePagination
endNumber={
pagination.currentPage * NUMBER_OF_OFFERS_IN_PAGE + offers.length
}
handlePageChange={handlePageChange}
pagination={pagination}
startNumber={pagination.currentPage * NUMBER_OF_OFFERS_IN_PAGE + 1}
/>
</div>
);
}

@ -6,7 +6,7 @@ export enum YOE_CATEGORY {
SENIOR = 3,
}
export const OfferTableTabOptions = [
export const OfferTableYoeOptions = [
{
label: 'Fresh Grad (0-2 YOE)',
value: YOE_CATEGORY.ENTRY,

@ -0,0 +1,26 @@
import clsx from 'clsx';
import React from 'react';
type Props = Readonly<{
children: React.ReactNode;
className?: string;
variant?: 'narrow' | 'normal';
}>;
export default function Container({
children,
className,
variant = 'normal',
}: Props) {
return (
<div
className={clsx(
'mx-auto px-4 sm:px-6 lg:px-8',
variant === 'normal' && 'max-w-7xl',
variant === 'narrow' && 'max-w-6xl',
className,
)}>
{children}
</div>
);
}

@ -5,10 +5,14 @@ import { Banner } from '@tih/ui';
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
import OffersTable from '~/components/offers/table/OffersTable';
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
import Container from '~/components/shared/Container';
import type { JobTitleType } from '~/components/shared/JobTitles';
import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
export default function OffersHomePage() {
const [jobTitleFilter, setjobTitleFilter] = useState('software-engineer');
const [jobTitleFilter, setJobTitleFilter] = useState<JobTitleType | ''>(
'software-engineer',
);
const [companyFilter, setCompanyFilter] = useState('');
const { event: gaEvent } = useGoogleAnalytics();
@ -42,14 +46,14 @@ export default function OffersHomePage() {
textSize="inherit"
onSelect={(option) => {
if (option) {
setjobTitleFilter(option.value);
setJobTitleFilter(option.value as JobTitleType);
gaEvent({
action: `offers.table_filter_job_title_${option.value}`,
category: 'engagement',
label: 'Filter by job title',
});
} else {
setjobTitleFilter('');
setJobTitleFilter('');
}
}}
/>
@ -74,12 +78,12 @@ export default function OffersHomePage() {
</div>
</div>
</div>
<div className="flex justify-center bg-white pb-20 pt-10">
<Container className="pb-20 pt-10">
<OffersTable
companyFilter={companyFilter}
jobTitleFilter={jobTitleFilter}
/>
</div>
</Container>
</main>
);
}

@ -19,7 +19,8 @@ export default function Banner({ children, size = 'md', onHide }: Props) {
size === 'xs' && 'text-xs',
)}>
<div className="mx-auto max-w-7xl py-2 px-3 sm:px-6 lg:px-8">
<div className="pr-16 sm:px-16 sm:text-center">
<div
className={clsx('text-center sm:px-16', onHide != null && 'pr-16')}>
<p className="font-medium text-white">{children}</p>
</div>
{onHide != null && (

Loading…
Cancel
Save