);
})}
From 3b4cba377169ea822643da38f2a92d8da2533f80 Mon Sep 17 00:00:00 2001
From: Keane Chan
Date: Tue, 25 Oct 2022 09:57:06 +0800
Subject: [PATCH 03/19] [resumes][feat] mobile responsiveness for form
---
apps/portal/src/pages/resumes/submit.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/portal/src/pages/resumes/submit.tsx b/apps/portal/src/pages/resumes/submit.tsx
index 7901056b..7bba34e7 100644
--- a/apps/portal/src/pages/resumes/submit.tsx
+++ b/apps/portal/src/pages/resumes/submit.tsx
@@ -293,7 +293,7 @@ export default function SubmitResumeForm({
required={true}
onChange={(val) => onValueChange('title', val)}
/>
-
+
{fileUploadError && (
{fileUploadError}
From db19a84080db7421dca1039d7ca27db93a0cddc6 Mon Sep 17 00:00:00 2001
From: Bryann Yeap Kok Keong
Date: Tue, 25 Oct 2022 10:40:55 +0800
Subject: [PATCH 06/19] [offers][chore] Speed up fetching of dashboard offers
---
.../portal/src/server/router/offers/offers.ts | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/apps/portal/src/server/router/offers/offers.ts b/apps/portal/src/server/router/offers/offers.ts
index 84756179..7d5ff908 100644
--- a/apps/portal/src/server/router/offers/offers.ts
+++ b/apps/portal/src/server/router/offers/offers.ts
@@ -73,7 +73,7 @@ export const offersRouter = createRouter().query('list', {
const order = getOrder(input.sortBy.charAt(0));
const sortingKey = input.sortBy.substring(1);
- let data = !yoeRange
+ const data = !yoeRange
? await ctx.prisma.offersOffer.findMany({
// Internship
include: {
@@ -303,11 +303,18 @@ export const offersRouter = createRouter().query('list', {
},
});
+ const startRecordIndex: number = input.limit * input.offset;
+ const endRecordIndex: number =
+ startRecordIndex + input.limit <= data.length
+ ? startRecordIndex + input.limit
+ : data.length;
+ let paginatedData = data.slice(startRecordIndex, endRecordIndex);
+
// CONVERTING
const currency = input.currency?.toUpperCase();
if (currency != null && currency in Currency) {
- data = await Promise.all(
- data.map(async (offer) => {
+ paginatedData = await Promise.all(
+ paginatedData.map(async (offer) => {
if (offer.offersFullTime?.totalCompensation != null) {
offer.offersFullTime.totalCompensation.value =
await convertWithDate(
@@ -367,13 +374,6 @@ export const offersRouter = createRouter().query('list', {
);
}
- const startRecordIndex: number = input.limit * input.offset;
- const endRecordIndex: number =
- startRecordIndex + input.limit <= data.length
- ? startRecordIndex + input.limit
- : data.length;
- const paginatedData = data.slice(startRecordIndex, endRecordIndex);
-
return getOffersResponseMapper(
paginatedData.map((offer) => dashboardOfferDtoMapper(offer)),
{
From 199fc1a8b999524ecca1c69a74ff9527c910420d Mon Sep 17 00:00:00 2001
From: Peirong <35712975+peironggg@users.noreply.github.com>
Date: Tue, 25 Oct 2022 12:08:07 +0800
Subject: [PATCH 07/19] [resumes][feat] url search params (#429)
* [resumes][feat] adapt useSearchParams
* [resumes][feat] clickable button from review info tags
---
apps/portal/src/pages/resumes/[resumeId].tsx | 92 +++++++++++++++-
apps/portal/src/pages/resumes/browse.tsx | 100 ++++++++++++++----
apps/portal/src/pages/resumes/submit.tsx | 6 +-
.../browse => utils/resumes}/resumeFilters.ts | 14 +--
.../src/utils/resumes/useSearchParams.ts | 26 +++++
5 files changed, 202 insertions(+), 36 deletions(-)
rename apps/portal/src/{components/resumes/browse => utils/resumes}/resumeFilters.ts (93%)
create mode 100644 apps/portal/src/utils/resumes/useSearchParams.ts
diff --git a/apps/portal/src/pages/resumes/[resumeId].tsx b/apps/portal/src/pages/resumes/[resumeId].tsx
index 38c7cf31..0d3ec979 100644
--- a/apps/portal/src/pages/resumes/[resumeId].tsx
+++ b/apps/portal/src/pages/resumes/[resumeId].tsx
@@ -21,9 +21,25 @@ import ResumeCommentsList from '~/components/resumes/comments/ResumeCommentsList
import ResumePdf from '~/components/resumes/ResumePdf';
import ResumeExpandableText from '~/components/resumes/shared/ResumeExpandableText';
+import type {
+ FilterOption,
+ LocationFilter,
+} from '~/utils/resumes/resumeFilters';
+import {
+ BROWSE_TABS_VALUES,
+ EXPERIENCES,
+ INITIAL_FILTER_STATE,
+ LOCATIONS,
+ ROLES,
+ SORT_OPTIONS,
+} from '~/utils/resumes/resumeFilters';
import { trpc } from '~/utils/trpc';
import SubmitResumeForm from './submit';
+import type {
+ ExperienceFilter,
+ RoleFilter,
+} from '../../utils/resumes/resumeFilters';
export default function ResumeReviewPage() {
const ErrorPage = (
@@ -57,7 +73,8 @@ export default function ResumeReviewPage() {
},
});
const userIsOwner =
- session?.user?.id != null && session.user.id === detailsQuery.data?.userId;
+ session?.user?.id !== undefined &&
+ session.user.id === detailsQuery.data?.userId;
const [isEditMode, setIsEditMode] = useState(false);
const [showCommentsForm, setShowCommentsForm] = useState(false);
@@ -79,6 +96,46 @@ export default function ResumeReviewPage() {
}
};
+ const onInfoTagClick = ({
+ locationLabel,
+ experienceLabel,
+ roleLabel,
+ }: {
+ experienceLabel?: string;
+ locationLabel?: string;
+ roleLabel?: string;
+ }) => {
+ const getFilterValue = (
+ label: string,
+ filterOptions: Array<
+ FilterOption
+ >,
+ ) => filterOptions.find((option) => option.label === label)?.value;
+
+ router.push({
+ pathname: '/resumes/browse',
+ query: {
+ currentPage: JSON.stringify(1),
+ searchValue: JSON.stringify(''),
+ shortcutSelected: JSON.stringify('all'),
+ sortOrder: JSON.stringify(SORT_OPTIONS.LATEST),
+ tabsValue: JSON.stringify(BROWSE_TABS_VALUES.ALL),
+ userFilters: JSON.stringify({
+ ...INITIAL_FILTER_STATE,
+ ...(locationLabel && {
+ location: [getFilterValue(locationLabel, LOCATIONS)],
+ }),
+ ...(roleLabel && {
+ role: [getFilterValue(roleLabel, ROLES)],
+ }),
+ ...(experienceLabel && {
+ experience: [getFilterValue(experienceLabel, EXPERIENCES)],
+ }),
+ }),
+ },
+ });
+ };
+
const onEditButtonClick = () => {
setIsEditMode(true);
};
@@ -199,21 +256,48 @@ export default function ResumeReviewPage() {
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-indigo-400"
/>
- {detailsQuery.data.role}
+
- {detailsQuery.data.location}
+
- {detailsQuery.data.experience}
+
{
+ return (
+ isTabsValueInit &&
+ isSortOrderInit &&
+ isSearchValueInit &&
+ isShortcutInit &&
+ isCurrentPageInit &&
+ isUserFiltersInit
+ );
+ }, [
+ isTabsValueInit,
+ isSortOrderInit,
+ isSearchValueInit,
+ isShortcutInit,
+ isCurrentPageInit,
+ isUserFiltersInit,
+ ]);
useEffect(() => {
setCurrentPage(1);
- }, [userFilters, sortOrder, searchValue]);
+ }, [userFilters, sortOrder, setCurrentPage, searchValue]);
+
+ useEffect(() => {
+ // Router.replace used instead of router.replace to avoid
+ // the page reloading itself since the router.replace
+ // callback changes on every page load
+ if (!isSearchOptionsInit) {
+ return;
+ }
+
+ Router.replace({
+ pathname: router.pathname,
+ query: {
+ currentPage: JSON.stringify(currentPage),
+ searchValue: JSON.stringify(searchValue),
+ shortcutSelected: JSON.stringify(shortcutSelected),
+ sortOrder: JSON.stringify(sortOrder),
+ tabsValue: JSON.stringify(tabsValue),
+ userFilters: JSON.stringify(userFilters),
+ },
+ });
+ }, [
+ tabsValue,
+ sortOrder,
+ searchValue,
+ userFilters,
+ shortcutSelected,
+ currentPage,
+ router.pathname,
+ isSearchOptionsInit,
+ ]);
const allResumesQuery = trpc.useQuery(
[
@@ -509,7 +569,7 @@ export default function ResumeHomePage() {
key={key}
isSelected={sortOrder === key}
label={value}
- onClick={() => setSortOrder(key)}>
+ onClick={() => setSortOrder(value)}>
))}
diff --git a/apps/portal/src/pages/resumes/submit.tsx b/apps/portal/src/pages/resumes/submit.tsx
index 7360c9de..182a32bd 100644
--- a/apps/portal/src/pages/resumes/submit.tsx
+++ b/apps/portal/src/pages/resumes/submit.tsx
@@ -19,14 +19,10 @@ import {
TextInput,
} from '@tih/ui';
-import {
- EXPERIENCES,
- LOCATIONS,
- ROLES,
-} from '~/components/resumes/browse/resumeFilters';
import SubmissionGuidelines from '~/components/resumes/submit-form/SubmissionGuidelines';
import { RESUME_STORAGE_KEY } from '~/constants/file-storage-keys';
+import { EXPERIENCES, LOCATIONS, ROLES } from '~/utils/resumes/resumeFilters';
import { trpc } from '~/utils/trpc';
const FILE_SIZE_LIMIT_MB = 3;
diff --git a/apps/portal/src/components/resumes/browse/resumeFilters.ts b/apps/portal/src/utils/resumes/resumeFilters.ts
similarity index 93%
rename from apps/portal/src/components/resumes/browse/resumeFilters.ts
rename to apps/portal/src/utils/resumes/resumeFilters.ts
index e0c4b0b5..1731647f 100644
--- a/apps/portal/src/components/resumes/browse/resumeFilters.ts
+++ b/apps/portal/src/utils/resumes/resumeFilters.ts
@@ -4,7 +4,7 @@ export type CustomFilter = {
numComments: number;
};
-type RoleFilter =
+export type RoleFilter =
| 'Android Engineer'
| 'Backend Engineer'
| 'DevOps Engineer'
@@ -12,7 +12,7 @@ type RoleFilter =
| 'Full-Stack Engineer'
| 'iOS Engineer';
-type ExperienceFilter =
+export type ExperienceFilter =
| 'Entry Level (0 - 2 years)'
| 'Freshman'
| 'Junior'
@@ -21,7 +21,7 @@ type ExperienceFilter =
| 'Senior'
| 'Sophomore';
-type LocationFilter = 'India' | 'Singapore' | 'United States';
+export type LocationFilter = 'India' | 'Singapore' | 'United States';
export type FilterValue = ExperienceFilter | LocationFilter | RoleFilter;
@@ -54,10 +54,10 @@ export const BROWSE_TABS_VALUES = {
STARRED: 'starred',
};
-export const SORT_OPTIONS: Record = {
- latest: 'Latest',
- popular: 'Popular',
- topComments: 'Most Comments',
+export const SORT_OPTIONS: Record = {
+ LATEST: 'latest',
+ POPULAR: 'popular',
+ TOPCOMMENTS: 'topComments',
};
export const ROLES: Array> = [
diff --git a/apps/portal/src/utils/resumes/useSearchParams.ts b/apps/portal/src/utils/resumes/useSearchParams.ts
new file mode 100644
index 00000000..0bea502c
--- /dev/null
+++ b/apps/portal/src/utils/resumes/useSearchParams.ts
@@ -0,0 +1,26 @@
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+
+export const useSearchParams = (name: string, defaultValue: T) => {
+ const [isInitialized, setIsInitialized] = useState(false);
+ const router = useRouter();
+
+ const [filters, setFilters] = useState(defaultValue);
+
+ useEffect(() => {
+ if (router.isReady && !isInitialized) {
+ // Initialize from url query params
+ const query = router.query[name];
+ if (query) {
+ const parsedQuery =
+ typeof query === 'string' ? JSON.parse(query) : query;
+ setFilters(parsedQuery);
+ }
+ setIsInitialized(true);
+ }
+ }, [isInitialized, name, router]);
+
+ return [filters, setFilters, isInitialized] as const;
+};
+
+export default useSearchParams;
From 05119f52fa9a8c036ccad0783a5fb6aa9221de3e Mon Sep 17 00:00:00 2001
From: Wu Peirong
Date: Tue, 25 Oct 2022 18:46:17 +0800
Subject: [PATCH 08/19] [resumes][fix] browse ui and sort order labels
---
apps/portal/src/pages/resumes/[resumeId].tsx | 3 +--
apps/portal/src/pages/resumes/browse.tsx | 23 +++++++++++--------
.../portal/src/utils/resumes/resumeFilters.ts | 16 +++++++++----
3 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/apps/portal/src/pages/resumes/[resumeId].tsx b/apps/portal/src/pages/resumes/[resumeId].tsx
index 0d3ec979..beb8c793 100644
--- a/apps/portal/src/pages/resumes/[resumeId].tsx
+++ b/apps/portal/src/pages/resumes/[resumeId].tsx
@@ -31,7 +31,6 @@ import {
INITIAL_FILTER_STATE,
LOCATIONS,
ROLES,
- SORT_OPTIONS,
} from '~/utils/resumes/resumeFilters';
import { trpc } from '~/utils/trpc';
@@ -118,7 +117,7 @@ export default function ResumeReviewPage() {
currentPage: JSON.stringify(1),
searchValue: JSON.stringify(''),
shortcutSelected: JSON.stringify('all'),
- sortOrder: JSON.stringify(SORT_OPTIONS.LATEST),
+ sortOrder: JSON.stringify('latest'),
tabsValue: JSON.stringify(BROWSE_TABS_VALUES.ALL),
userFilters: JSON.stringify({
...INITIAL_FILTER_STATE,
diff --git a/apps/portal/src/pages/resumes/browse.tsx b/apps/portal/src/pages/resumes/browse.tsx
index c48fb6ed..86e06a78 100644
--- a/apps/portal/src/pages/resumes/browse.tsx
+++ b/apps/portal/src/pages/resumes/browse.tsx
@@ -38,7 +38,7 @@ import useDebounceValue from '~/utils/resumes/useDebounceValue';
import useSearchParams from '~/utils/resumes/useSearchParams';
import { trpc } from '~/utils/trpc';
-import type { FilterState } from '../../utils/resumes/resumeFilters';
+import type { FilterState, SortOrder } from '../../utils/resumes/resumeFilters';
const STALE_TIME = 5 * 60 * 1000;
const DEBOUNCE_DELAY = 800;
@@ -102,9 +102,9 @@ export default function ResumeHomePage() {
'tabsValue',
BROWSE_TABS_VALUES.ALL,
);
- const [sortOrder, setSortOrder, isSortOrderInit] = useSearchParams(
+ const [sortOrder, setSortOrder, isSortOrderInit] = useSearchParams(
'sortOrder',
- SORT_OPTIONS.LATEST,
+ 'latest',
);
const [searchValue, setSearchValue, isSearchValueInit] = useSearchParams(
'searchValue',
@@ -491,7 +491,7 @@ export default function ResumeHomePage() {
{filter.options.map((option) => (
+ className="[&>div>div:nth-child(1)>input]:text-primary-600 [&>div>div:nth-child(1)>input]:ring-primary-500 px-1 [&>div>div:nth-child(2)>label]:font-normal">
-
- {Object.entries(SORT_OPTIONS).map(([key, value]) => (
+ value === sortOrder)
+ ?.label
+ }>
+ {SORT_OPTIONS.map(({ label, value }) => (
setSortOrder(value)}>
))}
diff --git a/apps/portal/src/utils/resumes/resumeFilters.ts b/apps/portal/src/utils/resumes/resumeFilters.ts
index 1731647f..3799e533 100644
--- a/apps/portal/src/utils/resumes/resumeFilters.ts
+++ b/apps/portal/src/utils/resumes/resumeFilters.ts
@@ -54,11 +54,17 @@ export const BROWSE_TABS_VALUES = {
STARRED: 'starred',
};
-export const SORT_OPTIONS: Record = {
- LATEST: 'latest',
- POPULAR: 'popular',
- TOPCOMMENTS: 'topComments',
-};
+// Export const SORT_OPTIONS: Record = {
+// LATEST: 'latest',
+// POPULAR: 'popular',
+// TOPCOMMENTS: 'topComments',
+// };
+
+export const SORT_OPTIONS: Array> = [
+ { label: 'Latest', value: 'latest' },
+ { label: 'Popular', value: 'popular' },
+ { label: 'Top Comments', value: 'topComments' },
+];
export const ROLES: Array> = [
{
From fa5cf0c115b0a972c7c0a6c9099ea43252d7cc3e Mon Sep 17 00:00:00 2001
From: Su Yin <53945359+tnsyn@users.noreply.github.com>
Date: Wed, 26 Oct 2022 13:18:51 +0800
Subject: [PATCH 09/19] [resumes][fix] Fix profile popup issue (#432)
---
apps/portal/src/pages/resumes/browse.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/portal/src/pages/resumes/browse.tsx b/apps/portal/src/pages/resumes/browse.tsx
index 86e06a78..f4ed682e 100644
--- a/apps/portal/src/pages/resumes/browse.tsx
+++ b/apps/portal/src/pages/resumes/browse.tsx
@@ -517,7 +517,7 @@ export default function ResumeHomePage() {