From b37aae215471c1d3d43004deaefca7c94245d7d5 Mon Sep 17 00:00:00 2001 From: Su Yin <53945359+tnsyn@users.noreply.github.com> Date: Sat, 8 Oct 2022 00:26:16 +0800 Subject: [PATCH] [resumes][feat] Fetch all resumes in browse page (#325) * [resumes][fix] Remove BrowsePageBody component * [resumes][feat] Add router to fetch all resumes * [resumes][feat] Fetch all resumes in browse page * [resumes][chore] Add todo * [resumes][fix] Remove unnecessary updatedAt field * [resumes][fix] Change from resumeProfile to user --- .../resumes/browse/BrowseListItem.tsx | 13 +- .../resumes/browse/BrowsePageBody.tsx | 226 ----------------- apps/portal/src/pages/resumes/index.tsx | 233 +++++++++++++++++- apps/portal/src/server/router/index.ts | 2 + apps/portal/src/server/router/resumes.ts | 42 ++++ apps/portal/src/types/resume.d.ts | 13 + 6 files changed, 291 insertions(+), 238 deletions(-) delete mode 100644 apps/portal/src/components/resumes/browse/BrowsePageBody.tsx create mode 100644 apps/portal/src/server/router/resumes.ts create mode 100644 apps/portal/src/types/resume.d.ts diff --git a/apps/portal/src/components/resumes/browse/BrowseListItem.tsx b/apps/portal/src/components/resumes/browse/BrowseListItem.tsx index a9d9c438..3588f0c0 100644 --- a/apps/portal/src/components/resumes/browse/BrowseListItem.tsx +++ b/apps/portal/src/components/resumes/browse/BrowseListItem.tsx @@ -3,19 +3,11 @@ import type { UrlObject } from 'url'; import { ChevronRightIcon } from '@heroicons/react/20/solid'; import { ChatBubbleLeftIcon, StarIcon } from '@heroicons/react/24/outline'; -type ResumeInfo = Readonly<{ - createdAt: Date; - experience: string; - numComments: number; - numStars: number; - role: string; - title: string; - user: string; -}>; +import type { Resume } from '~/types/resume'; type Props = Readonly<{ href: UrlObject | string; - resumeInfo: ResumeInfo; + resumeInfo: Resume; }>; export default function BrowseListItem({ href, resumeInfo }: Props) { @@ -42,6 +34,7 @@ export default function BrowseListItem({ href, resumeInfo }: Props) {
+ {/* TODO: Replace hardcoded days ago with calculated days ago*/} Uploaded 2 days ago by {resumeInfo.user}
diff --git a/apps/portal/src/components/resumes/browse/BrowsePageBody.tsx b/apps/portal/src/components/resumes/browse/BrowsePageBody.tsx deleted file mode 100644 index ee28609f..00000000 --- a/apps/portal/src/components/resumes/browse/BrowsePageBody.tsx +++ /dev/null @@ -1,226 +0,0 @@ -import clsx from 'clsx'; -import { Fragment, useState } from 'react'; -import { Disclosure, Menu, Transition } from '@headlessui/react'; -import { - ChevronDownIcon, - MinusIcon, - PlusIcon, -} from '@heroicons/react/20/solid'; -import { MagnifyingGlassIcon } from '@heroicons/react/24/outline'; -import { Tabs, TextInput } from '@tih/ui'; - -import BrowseListItem from './BrowseListItem'; -import { - EXPERIENCE, - LOCATION, - ROLES, - SORT_OPTIONS, - TEST_RESUMES, - TOP_HITS, -} from './constants'; -import FilterPill from './FilterPill'; - -const filters = [ - { - id: 'roles', - name: 'Roles', - options: ROLES, - }, - { - id: 'experience', - name: 'Experience', - options: EXPERIENCE, - }, - { - id: 'location', - name: 'Location', - options: LOCATION, - }, -]; - -export default function BrowsePageBody() { - const [tabsValue, setTabsValue] = useState('all'); - const [searchValue, setSearchValue] = useState(''); - return ( -
-
-
-

Filters

-
-
-
-
- -
-
-
- - -
-
- -
- - Sort - -
- - - -
- {SORT_OPTIONS.map((option) => ( - - {({ active }) => ( - - {option.name} - - )} - - ))} -
-
-
-
-
-
- -
-
-
-
- -
-
-
-
-

Categories

-
    - {TOP_HITS.map((category) => ( -
  • - {/* TODO: Replace onClick with filtering function */} - true} /> -
  • - ))} -
- - {filters.map((section) => ( - - {({ open }) => ( - <> -

- - - {section.name} - - - {open ? ( - - -

- -
- {section.options.map((option, optionIdx) => ( -
- - -
- ))} -
-
- - )} -
- ))} -
-
-
-
-
    - {TEST_RESUMES.map((resumeObj) => ( -
  • - -
  • - ))} -
-
-
-
- ); -} diff --git a/apps/portal/src/pages/resumes/index.tsx b/apps/portal/src/pages/resumes/index.tsx index f0f9bad1..fb0ca8b0 100644 --- a/apps/portal/src/pages/resumes/index.tsx +++ b/apps/portal/src/pages/resumes/index.tsx @@ -1,14 +1,243 @@ -import BrowsePageBody from '~/components/resumes/browse/BrowsePageBody'; +import clsx from 'clsx'; +import { Fragment, useState } from 'react'; +import { Disclosure, Menu, Transition } from '@headlessui/react'; +import { + ChevronDownIcon, + MinusIcon, + PlusIcon, +} from '@heroicons/react/20/solid'; +import { MagnifyingGlassIcon } from '@heroicons/react/24/outline'; +import { Tabs, TextInput } from '@tih/ui'; + +import BrowseListItem from '~/components/resumes/browse/BrowseListItem'; +import { + EXPERIENCE, + LOCATION, + ROLES, + SORT_OPTIONS, + TOP_HITS, +} from '~/components/resumes/browse/constants'; +import FilterPill from '~/components/resumes/browse/FilterPill'; + +const filters = [ + { + id: 'roles', + name: 'Roles', + options: ROLES, + }, + { + id: 'experience', + name: 'Experience', + options: EXPERIENCE, + }, + { + id: 'location', + name: 'Location', + options: LOCATION, + }, +]; import ResumeReviewsTitle from '~/components/resumes/ResumeReviewsTitle'; +import { trpc } from '~/utils/trpc'; + export default function ResumeHomePage() { + const [tabsValue, setTabsValue] = useState('all'); + const [searchValue, setSearchValue] = useState(''); + const resumesQuery = trpc.useQuery(['resumes.resume.list']); + return (
- +
+
+
+

Filters

+
+
+
+
+ +
+
+
+ + +
+
+ +
+ + Sort + +
+ + + +
+ {SORT_OPTIONS.map((option) => ( + + {({ active }) => ( + + {option.name} + + )} + + ))} +
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+

Categories

+
    + {TOP_HITS.map((category) => ( +
  • + {/* TODO: Replace onClick with filtering function */} + true} + /> +
  • + ))} +
+ + {filters.map((section) => ( + + {({ open }) => ( + <> +

+ + + {section.name} + + + {open ? ( + + +

+ +
+ {section.options.map((option, optionIdx) => ( +
+ + +
+ ))} +
+
+ + )} +
+ ))} +
+
+
+ {resumesQuery.isLoading ? ( +
Loading...
+ ) : ( +
+
    + {resumesQuery.data?.map((resumeObj) => ( +
  • + +
  • + ))} +
+
+ )} +
+
); diff --git a/apps/portal/src/server/router/index.ts b/apps/portal/src/server/router/index.ts index 16530ff6..ddeff431 100644 --- a/apps/portal/src/server/router/index.ts +++ b/apps/portal/src/server/router/index.ts @@ -2,6 +2,7 @@ import superjson from 'superjson'; import { createRouter } from './context'; import { protectedExampleRouter } from './protected-example-router'; +import { resumesRouter } from './resumes'; import { resumesDetailsRouter } from './resumes-details-router'; import { resumesResumeUserRouter } from './resumes-resume-user-router'; import { resumeReviewsRouter } from './resumes-reviews-router'; @@ -17,6 +18,7 @@ export const appRouter = createRouter() .merge('auth.', protectedExampleRouter) .merge('todos.', todosRouter) .merge('todos.user.', todosUserRouter) + .merge('resumes.resume.', resumesRouter) .merge('resumes.details.', resumesDetailsRouter) .merge('resumes.resume.user.', resumesResumeUserRouter) .merge('resumes.reviews.', resumeReviewsRouter) diff --git a/apps/portal/src/server/router/resumes.ts b/apps/portal/src/server/router/resumes.ts new file mode 100644 index 00000000..2e7f9f9c --- /dev/null +++ b/apps/portal/src/server/router/resumes.ts @@ -0,0 +1,42 @@ +import { createRouter } from './context'; + +import type { Resume } from '~/types/resume'; + +export const resumesRouter = createRouter().query('list', { + async resolve({ ctx }) { + const resumesData = await ctx.prisma.resumesResume.findMany({ + include: { + _count: { + select: { + comments: true, + stars: true, + }, + }, + user: { + select: { + name: true, + }, + }, + }, + orderBy: { + createdAt: 'desc', + }, + }); + return resumesData.map((r) => { + const resume: Resume = { + additionalInfo: r.additionalInfo, + createdAt: r.createdAt, + experience: r.experience, + id: r.id, + location: r.location, + numComments: r._count.comments, + numStars: r._count.stars, + role: r.role, + title: r.title, + url: r.url, + user: r.user.name!, + }; + return resume; + }); + }, +}); diff --git a/apps/portal/src/types/resume.d.ts b/apps/portal/src/types/resume.d.ts new file mode 100644 index 00000000..5b2a33a9 --- /dev/null +++ b/apps/portal/src/types/resume.d.ts @@ -0,0 +1,13 @@ +export type Resume = { + additionalInfo: string?; + createdAt: Date; + experience: string; + id: string; + location: string; + numComments: number; + numStars: number; + role: string; + title: string; + url: string; + user: string; +};