From 0eb4f3fc5b4f8e21bfc3b67b44fce34d76004aa6 Mon Sep 17 00:00:00 2001 From: Zhang Ziqing <69516975+ziqing26@users.noreply.github.com> Date: Wed, 12 Oct 2022 19:50:41 +0800 Subject: [PATCH] [offers][feat] add table loading status, refactor table (#368) --- .../offers/forms/BackgroundForm.tsx | 13 +- .../components/offers/forms/OfferAnalysis.tsx | 3 +- .../offers/forms/components/FormTextArea.tsx | 3 +- .../offers/profile/ProfileHeader.tsx | 3 +- .../src/components/offers/table/OffersRow.tsx | 32 ++++ .../offers/{ => table}/OffersTable.tsx | 166 +++++------------- .../offers/table/OffersTablePagination.tsx | 44 +++++ .../src/components/offers/table/types.ts | 24 +++ .../questions/ContributeQuestionDialog.tsx | 3 +- apps/portal/src/pages/offers/index.tsx | 2 +- .../pages/offers/profile/[offerProfileId].tsx | 5 +- 11 files changed, 157 insertions(+), 141 deletions(-) create mode 100644 apps/portal/src/components/offers/table/OffersRow.tsx rename apps/portal/src/components/offers/{ => table}/OffersTable.tsx (56%) create mode 100644 apps/portal/src/components/offers/table/OffersTablePagination.tsx create mode 100644 apps/portal/src/components/offers/table/types.ts diff --git a/apps/portal/src/components/offers/forms/BackgroundForm.tsx b/apps/portal/src/components/offers/forms/BackgroundForm.tsx index 171823f1..61a1c3fe 100644 --- a/apps/portal/src/components/offers/forms/BackgroundForm.tsx +++ b/apps/portal/src/components/offers/forms/BackgroundForm.tsx @@ -1,18 +1,19 @@ import { useFormContext, useWatch } from 'react-hook-form'; import { Collapsible, RadioList } from '@tih/ui'; -import FormRadioList from './components/FormRadioList'; -import FormSelect from './components/FormSelect'; -import FormTextInput from './components/FormTextInput'; import { companyOptions, educationFieldOptions, educationLevelOptions, locationOptions, titleOptions, -} from '../constants'; -import { JobType } from '../types'; -import { CURRENCY_OPTIONS } from '../../../utils/offers/currency/CurrencyEnum'; +} from '~/components/offers/constants'; +import FormRadioList from '~/components/offers/forms/components/FormRadioList'; +import FormSelect from '~/components/offers/forms/components/FormSelect'; +import FormTextInput from '~/components/offers/forms/components/FormTextInput'; +import { JobType } from '~/components/offers/types'; + +import { CURRENCY_OPTIONS } from '~/utils/offers/currency/CurrencyEnum'; function YoeSection() { const { register } = useFormContext(); diff --git a/apps/portal/src/components/offers/forms/OfferAnalysis.tsx b/apps/portal/src/components/offers/forms/OfferAnalysis.tsx index b0b7133c..c3625d6d 100644 --- a/apps/portal/src/components/offers/forms/OfferAnalysis.tsx +++ b/apps/portal/src/components/offers/forms/OfferAnalysis.tsx @@ -1,7 +1,6 @@ import { useState } from 'react'; import { UserCircleIcon } from '@heroicons/react/20/solid'; - -import { HorizontalDivider, Tabs } from '~/../../../packages/ui/dist'; +import { HorizontalDivider, Tabs } from '@tih/ui'; const tabs = [ { diff --git a/apps/portal/src/components/offers/forms/components/FormTextArea.tsx b/apps/portal/src/components/offers/forms/components/FormTextArea.tsx index f833c3dd..20f606cf 100644 --- a/apps/portal/src/components/offers/forms/components/FormTextArea.tsx +++ b/apps/portal/src/components/offers/forms/components/FormTextArea.tsx @@ -1,8 +1,7 @@ import type { ComponentProps, ForwardedRef } from 'react'; import { forwardRef } from 'react'; import type { UseFormRegisterReturn } from 'react-hook-form'; - -import { TextArea } from '~/../../../packages/ui/dist'; +import { TextArea } from '@tih/ui'; type TextAreaProps = ComponentProps; diff --git a/apps/portal/src/components/offers/profile/ProfileHeader.tsx b/apps/portal/src/components/offers/profile/ProfileHeader.tsx index f2dca77e..c37b40ff 100644 --- a/apps/portal/src/components/offers/profile/ProfileHeader.tsx +++ b/apps/portal/src/components/offers/profile/ProfileHeader.tsx @@ -8,10 +8,9 @@ import { } from '@heroicons/react/24/outline'; import { Button, Dialog, Spinner, Tabs } from '@tih/ui'; +import ProfilePhotoHolder from '~/components/offers/profile/ProfilePhotoHolder'; import type { BackgroundCard } from '~/components/offers/types'; -import ProfilePhotoHolder from './ProfilePhotoHolder'; - type ProfileHeaderProps = Readonly<{ background?: BackgroundCard; handleDelete: () => void; diff --git a/apps/portal/src/components/offers/table/OffersRow.tsx b/apps/portal/src/components/offers/table/OffersRow.tsx new file mode 100644 index 00000000..8ab39bdd --- /dev/null +++ b/apps/portal/src/components/offers/table/OffersRow.tsx @@ -0,0 +1,32 @@ +import Link from 'next/link'; + +import type { OfferTableRowData } from '~/components/offers/table/types'; + +export type OfferTableRowProps = Readonly<{ row: OfferTableRowData }>; + +export default function OfferTableRow({ + row: { company, date, id, profileId, salary, title, yoe }, +}: OfferTableRowProps) { + return ( + + + {company} + + {title} + {yoe} + {salary} + {date} + + + View Profile + + + + ); +} diff --git a/apps/portal/src/components/offers/OffersTable.tsx b/apps/portal/src/components/offers/table/OffersTable.tsx similarity index 56% rename from apps/portal/src/components/offers/OffersTable.tsx rename to apps/portal/src/components/offers/table/OffersTable.tsx index 5bebccc9..bfc74285 100644 --- a/apps/portal/src/components/offers/OffersTable.tsx +++ b/apps/portal/src/components/offers/table/OffersTable.tsx @@ -1,54 +1,34 @@ -import Link from 'next/link'; import { useEffect, useState } from 'react'; -import { HorizontalDivider, Pagination, Select, Tabs } from '@tih/ui'; +import { HorizontalDivider, Select, Spinner, Tabs } from '@tih/ui'; + +import OffersTablePagination from '~/components/offers/table/OffersTablePagination'; +import type { + OfferTableRowData, + PaginationType, +} from '~/components/offers/table/types'; +import { YOE_CATEGORY } from '~/components/offers/table/types'; import CurrencySelector from '~/utils/offers/currency/CurrencySelector'; import { formatDate } from '~/utils/offers/time'; import { trpc } from '~/utils/trpc'; -type OfferTableRow = { - company: string; - date: string; - id: string; - profileId: string; - salary: number | undefined; - title: string; - yoe: number; -}; - -// To be changed to backend enum -// eslint-disable-next-line no-shadow -enum YOE_CATEGORY { - INTERN = 0, - ENTRY = 1, - MID = 2, - SENIOR = 3, -} - -type OffersTableProps = { - companyFilter: string; - jobTitleFilter: string; -}; - -type Pagination = { - currentPage: number; - numOfItems: number; - numOfPages: number; - totalItems: number; -}; +import OffersRow from './OffersRow'; const NUMBER_OF_OFFERS_IN_PAGE = 10; - +export type OffersTableProps = Readonly<{ + companyFilter: string; + jobTitleFilter: string; +}>; export default function OffersTable({ jobTitleFilter }: OffersTableProps) { - const [currency, setCurrency] = useState('SGD'); // TODO + const [currency, setCurrency] = useState('SGD'); // TODO: Detect location const [selectedTab, setSelectedTab] = useState(YOE_CATEGORY.ENTRY); - const [pagination, setPagination] = useState({ + const [pagination, setPagination] = useState({ currentPage: 1, numOfItems: 1, numOfPages: 0, totalItems: 0, }); - const [offers, setOffers] = useState>([]); + const [offers, setOffers] = useState>([]); useEffect(() => { setPagination({ @@ -58,7 +38,7 @@ export default function OffersTable({ jobTitleFilter }: OffersTableProps) { totalItems: 0, }); }, [selectedTab]); - trpc.useQuery( + const offersQuery = trpc.useQuery( [ 'offers.list', { @@ -166,7 +146,7 @@ export default function OffersTable({ jobTitleFilter }: OffersTableProps) { 'Company', 'Title', 'YOE', - 'TC/year', + selectedTab === YOE_CATEGORY.INTERN ? 'Monthly Salary' : 'TC/year', 'Date offered', 'Actions', ].map((header) => ( @@ -183,97 +163,37 @@ export default function OffersTable({ jobTitleFilter }: OffersTableProps) { setPagination({ ...pagination, currentPage: currPage }); }; - function renderRow({ - company, - title, - yoe, - salary, - date, - profileId, - id, - }: OfferTableRow) { - return ( - - - {company} - - {title} - {yoe} - {salary} - {date} - - {/* handleClickViewProfile(profileId)}> - View Profile - */} - - - View Profile - - {/* - Comment - */} - - - ); - } - - function renderPagination() { - return ( - - ); - } - return (
{renderTabs()}
{renderFilters()} - - {renderHeader()} - - {offers.map((offer: OfferTableRow) => renderRow(offer))} - -
- {renderPagination()} + {offersQuery.isLoading ? ( +
+ +
+ ) : ( + + {renderHeader()} + + {offers.map((offer) => ( + + ))} + +
+ )} +
); diff --git a/apps/portal/src/components/offers/table/OffersTablePagination.tsx b/apps/portal/src/components/offers/table/OffersTablePagination.tsx new file mode 100644 index 00000000..e7346c44 --- /dev/null +++ b/apps/portal/src/components/offers/table/OffersTablePagination.tsx @@ -0,0 +1,44 @@ +import { Pagination } from '@tih/ui'; + +import type { PaginationType } from '~/components/offers/table/types'; + +type OffersTablePaginationProps = Readonly<{ + endNumber: number; + handlePageChange: (page: number) => void; + pagination: PaginationType; + startNumber: number; +}>; + +export default function OffersTablePagination({ + endNumber, + pagination, + startNumber, + handlePageChange, +}: OffersTablePaginationProps) { + return ( + + ); +} diff --git a/apps/portal/src/components/offers/table/types.ts b/apps/portal/src/components/offers/table/types.ts new file mode 100644 index 00000000..9522a9bb --- /dev/null +++ b/apps/portal/src/components/offers/table/types.ts @@ -0,0 +1,24 @@ +export type OfferTableRowData = { + company: string; + date: string; + id: string; + profileId: string; + salary: number | undefined; + title: string; + yoe: number; +}; + +// eslint-disable-next-line no-shadow +export enum YOE_CATEGORY { + INTERN = 0, + ENTRY = 1, + MID = 2, + SENIOR = 3, +} + +export type PaginationType = { + currentPage: number; + numOfItems: number; + numOfPages: number; + totalItems: number; +}; diff --git a/apps/portal/src/components/questions/ContributeQuestionDialog.tsx b/apps/portal/src/components/questions/ContributeQuestionDialog.tsx index 65cb1058..b21b21dc 100644 --- a/apps/portal/src/components/questions/ContributeQuestionDialog.tsx +++ b/apps/portal/src/components/questions/ContributeQuestionDialog.tsx @@ -1,7 +1,6 @@ import { Fragment, useState } from 'react'; import { Dialog, Transition } from '@headlessui/react'; - -import { HorizontalDivider } from '~/../../../packages/ui/dist'; +import { HorizontalDivider } from '@tih/ui'; import type { ContributeQuestionFormProps } from './ContributeQuestionForm'; import ContributeQuestionForm from './ContributeQuestionForm'; diff --git a/apps/portal/src/pages/offers/index.tsx b/apps/portal/src/pages/offers/index.tsx index b948139e..f690fa27 100644 --- a/apps/portal/src/pages/offers/index.tsx +++ b/apps/portal/src/pages/offers/index.tsx @@ -1,8 +1,8 @@ import { useState } from 'react'; import { Select } from '@tih/ui'; -import OffersTable from '~/components/offers/OffersTable'; import OffersTitle from '~/components/offers/OffersTitle'; +import OffersTable from '~/components/offers/table/OffersTable'; import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead'; export default function OffersHomePage() { diff --git a/apps/portal/src/pages/offers/profile/[offerProfileId].tsx b/apps/portal/src/pages/offers/profile/[offerProfileId].tsx index ae320d5a..1ecfd8ea 100644 --- a/apps/portal/src/pages/offers/profile/[offerProfileId].tsx +++ b/apps/portal/src/pages/offers/profile/[offerProfileId].tsx @@ -2,15 +2,14 @@ import Error from 'next/error'; import { useRouter } from 'next/router'; import { useState } from 'react'; +import ProfileComments from '~/components/offers/profile/ProfileComments'; +import ProfileDetails from '~/components/offers/profile/ProfileDetails'; import ProfileHeader from '~/components/offers/profile/ProfileHeader'; import type { OfferEntity } from '~/components/offers/types'; import type { BackgroundCard } from '~/components/offers/types'; import { formatDate } from '~/utils/offers/time'; import { trpc } from '~/utils/trpc'; - -import ProfileComments from '../../../components/offers/profile/ProfileComments'; -import ProfileDetails from '../../../components/offers/profile/ProfileDetails'; export default function OfferProfile() { const ErrorPage = (