From a208435dad4a4ab005a05c671501820e5814cbd9 Mon Sep 17 00:00:00 2001 From: Jeff Sieu Date: Mon, 31 Oct 2022 16:38:56 +0800 Subject: [PATCH 01/33] [questions][fix] fix contribute dialog close (#476) --- .../questions/ContributeQuestionCard.tsx | 88 ++++++++++--------- .../questions/ContributeQuestionDialog.tsx | 7 +- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/apps/portal/src/components/questions/ContributeQuestionCard.tsx b/apps/portal/src/components/questions/ContributeQuestionCard.tsx index ae53a914..f91e1eb4 100644 --- a/apps/portal/src/components/questions/ContributeQuestionCard.tsx +++ b/apps/portal/src/components/questions/ContributeQuestionCard.tsx @@ -30,54 +30,56 @@ export default function ContributeQuestionCard({ }); return ( - - + ); } diff --git a/apps/portal/src/components/questions/ContributeQuestionDialog.tsx b/apps/portal/src/components/questions/ContributeQuestionDialog.tsx index ae08724b..8e481632 100644 --- a/apps/portal/src/components/questions/ContributeQuestionDialog.tsx +++ b/apps/portal/src/components/questions/ContributeQuestionDialog.tsx @@ -35,7 +35,12 @@ export default function ContributeQuestionDialog({ return (
- + { + onCancel(); + }}> Date: Mon, 31 Oct 2022 17:28:53 +0800 Subject: [PATCH 02/33] [questions][fix] fix landing page company param (#477) --- .../components/questions/LandingComponent.tsx | 7 ++++--- apps/portal/src/pages/questions/browse.tsx | 18 +++++++----------- apps/portal/src/pages/questions/index.tsx | 4 ++-- apps/portal/src/utils/questions/companySlug.ts | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 apps/portal/src/utils/questions/companySlug.ts diff --git a/apps/portal/src/components/questions/LandingComponent.tsx b/apps/portal/src/components/questions/LandingComponent.tsx index f2578c4d..336c185a 100644 --- a/apps/portal/src/components/questions/LandingComponent.tsx +++ b/apps/portal/src/components/questions/LandingComponent.tsx @@ -3,6 +3,7 @@ import { ArrowSmallRightIcon } from '@heroicons/react/24/outline'; import type { QuestionsQuestionType } from '@prisma/client'; import { Button, Select } from '@tih/ui'; +import { companyOptionToSlug } from '~/utils/questions/companySlug'; import { QUESTION_TYPES } from '~/utils/questions/constants'; import useDefaultCompany from '~/utils/questions/useDefaultCompany'; import useDefaultLocation from '~/utils/questions/useDefaultLocation'; @@ -12,7 +13,7 @@ import CompanyTypeahead from './typeahead/CompanyTypeahead'; import LocationTypeahead from './typeahead/LocationTypeahead'; export type LandingQueryData = { - company: string; + companySlug: string; location: string; questionType: QuestionsQuestionType; }; @@ -71,7 +72,7 @@ export default function LandingComponent({ className="h-40 w-40" src="/bank-logo.png" /> -

+

Tech Interview Question Bank

@@ -124,7 +125,7 @@ export default function LandingComponent({ onClick={() => { if (company !== undefined && location !== undefined) { return handleLandingQuery({ - company: company.label, + companySlug: companyOptionToSlug(company), location: location.value, questionType, }); diff --git a/apps/portal/src/pages/questions/browse.tsx b/apps/portal/src/pages/questions/browse.tsx index 9a974f5d..c08e189e 100644 --- a/apps/portal/src/pages/questions/browse.tsx +++ b/apps/portal/src/pages/questions/browse.tsx @@ -18,6 +18,10 @@ import LocationTypeahead from '~/components/questions/typeahead/LocationTypeahea import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead'; import { JobTitleLabels } from '~/components/shared/JobTitles'; +import { + companyOptionToSlug, + slugToCompanyOption, +} from '~/utils/questions/companySlug'; import type { QuestionAge } from '~/utils/questions/constants'; import { APP_TITLE } from '~/utils/questions/constants'; import { QUESTION_AGES, QUESTION_TYPES } from '~/utils/questions/constants'; @@ -288,15 +292,7 @@ export default function QuestionsBrowsePage() { ]); const selectedCompanyOptions = useMemo(() => { - return selectedCompanySlugs.map((company) => { - const [id, label] = company.split('_'); - return { - checked: true, - id, - label, - value: id, - }; - }); + return selectedCompanySlugs.map(slugToCompanyOption); }, [selectedCompanySlugs]); const selectedRoleOptions = useMemo(() => { @@ -363,12 +359,12 @@ export default function QuestionsBrowsePage() { if (option.checked) { setSelectedCompanySlugs([ ...selectedCompanySlugs, - `${option.id}_${option.label}`, + companyOptionToSlug(option), ]); } else { setSelectedCompanySlugs( selectedCompanySlugs.filter( - (companySlug) => companySlug !== `${option.id}_${option.label}`, + (companySlug) => companySlug !== companyOptionToSlug(option), ), ); } diff --git a/apps/portal/src/pages/questions/index.tsx b/apps/portal/src/pages/questions/index.tsx index 0f5f07f1..37999946 100644 --- a/apps/portal/src/pages/questions/index.tsx +++ b/apps/portal/src/pages/questions/index.tsx @@ -10,13 +10,13 @@ export default function QuestionsHomePage() { const router = useRouter(); const handleLandingQuery = async (data: LandingQueryData) => { - const { company, location, questionType } = data; + const { companySlug, location, questionType } = data; // Go to browse page router.push({ pathname: '/questions/browse', query: { - companies: [company], + companies: [companySlug], locations: [location], questionTypes: [questionType], }, diff --git a/apps/portal/src/utils/questions/companySlug.ts b/apps/portal/src/utils/questions/companySlug.ts new file mode 100644 index 00000000..bba52c4a --- /dev/null +++ b/apps/portal/src/utils/questions/companySlug.ts @@ -0,0 +1,18 @@ +import type { + FilterChoice, + FilterOption, +} from '~/components/questions/filter/FilterSection'; + +export function companyOptionToSlug(option: FilterChoice): string { + return `${option.id}_${option.label}`; +} + +export function slugToCompanyOption(slug: string): FilterOption { + const [id, label] = slug.split('_'); + return { + checked: true, + id, + label, + value: id, + }; +} From 84768a1cb6900165449076ec342a9198f2c80d26 Mon Sep 17 00:00:00 2001 From: Zhang Ziqing <69516975+ziqing26@users.noreply.github.com> Date: Mon, 31 Oct 2022 17:34:16 +0800 Subject: [PATCH 03/33] [offers][style] fix style for safari (#479) --- .../components/global/ProductNavigation.tsx | 18 ++++++++++-------- .../offers/profile/ProfileHeader.tsx | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/portal/src/components/global/ProductNavigation.tsx b/apps/portal/src/components/global/ProductNavigation.tsx index aeff5e80..bdd8efd6 100644 --- a/apps/portal/src/components/global/ProductNavigation.tsx +++ b/apps/portal/src/components/global/ProductNavigation.tsx @@ -35,14 +35,16 @@ export default function ProductNavigation({ - {titleHref !== '/' && - (logo ?? ( - Tech Interview Handbook - ))} +
+ {titleHref !== '/' && + (logo ?? ( + Tech Interview Handbook + ))} +
{title}
diff --git a/apps/portal/src/components/offers/profile/ProfileHeader.tsx b/apps/portal/src/components/offers/profile/ProfileHeader.tsx index 1b0770a1..f2e087a4 100644 --- a/apps/portal/src/components/offers/profile/ProfileHeader.tsx +++ b/apps/portal/src/components/offers/profile/ProfileHeader.tsx @@ -235,7 +235,7 @@ export default function ProfileHeader({ return (
-
+
From d4283eb52240a978808ffa8f2f260645d8a35f09 Mon Sep 17 00:00:00 2001 From: Ren Weilin <66356390+wlren@users.noreply.github.com> Date: Mon, 31 Oct 2022 17:46:30 +0800 Subject: [PATCH 04/33] [questions][ui] fix contribute button (#480) --- .../src/components/questions/forms/ContributeQuestionForm.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/portal/src/components/questions/forms/ContributeQuestionForm.tsx b/apps/portal/src/components/questions/forms/ContributeQuestionForm.tsx index faf8d25d..8f4105b9 100644 --- a/apps/portal/src/components/questions/forms/ContributeQuestionForm.tsx +++ b/apps/portal/src/components/questions/forms/ContributeQuestionForm.tsx @@ -278,6 +278,7 @@ export default function ContributeQuestionForm({ From 6c53956551e5610f1ce05c94d4b37debf4e78c82 Mon Sep 17 00:00:00 2001 From: Zhang Ziqing <69516975+ziqing26@users.noreply.github.com> Date: Mon, 31 Oct 2022 17:47:18 +0800 Subject: [PATCH 05/33] [offers][fix] fix date display for single value (#481) --- apps/portal/src/utils/offers/time.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/portal/src/utils/offers/time.tsx b/apps/portal/src/utils/offers/time.tsx index ffa3c545..5c7305dd 100644 --- a/apps/portal/src/utils/offers/time.tsx +++ b/apps/portal/src/utils/offers/time.tsx @@ -9,19 +9,23 @@ export function timeSinceNow(date: Date | number | string) { let interval = seconds / 31536000; if (interval > 1) { - return `${Math.floor(interval)} years`; + const time: number = Math.floor(interval); + return time === 1 ? `${time} year` : `${time} years`; } interval = seconds / 2592000; if (interval > 1) { - return `${Math.floor(interval)} months`; + const time: number = Math.floor(interval); + return time === 1 ? `${time} month` : `${time} months`; } interval = seconds / 86400; if (interval > 1) { - return `${Math.floor(interval)} days`; + const time: number = Math.floor(interval); + return time === 1 ? `${time} day` : `${time} days`; } interval = seconds / 3600; if (interval > 1) { - return `${Math.floor(interval)} hours`; + const time: number = Math.floor(interval); + return time === 1 ? `${time} hour` : `${time} hours`; } interval = seconds / 60; if (interval > 1) { From 3cc238b0ce8ab7b5d372f8a68b3222d4d74b6508 Mon Sep 17 00:00:00 2001 From: Jeff Sieu Date: Mon, 31 Oct 2022 18:09:41 +0800 Subject: [PATCH 06/33] [questions][fix] fix landing page location params (#482) --- .../components/questions/LandingComponent.tsx | 14 +++++--- apps/portal/src/pages/questions/browse.tsx | 34 ++++++++----------- .../questions/questions-question-router.ts | 1 + .../src/utils/questions/locationSlug.ts | 16 +++++++++ 4 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 apps/portal/src/utils/questions/locationSlug.ts diff --git a/apps/portal/src/components/questions/LandingComponent.tsx b/apps/portal/src/components/questions/LandingComponent.tsx index 336c185a..2349c042 100644 --- a/apps/portal/src/components/questions/LandingComponent.tsx +++ b/apps/portal/src/components/questions/LandingComponent.tsx @@ -1,10 +1,12 @@ import { useEffect, useState } from 'react'; import { ArrowSmallRightIcon } from '@heroicons/react/24/outline'; import type { QuestionsQuestionType } from '@prisma/client'; +import type { TypeaheadOption } from '@tih/ui'; import { Button, Select } from '@tih/ui'; import { companyOptionToSlug } from '~/utils/questions/companySlug'; import { QUESTION_TYPES } from '~/utils/questions/constants'; +import { locationOptionToSlug } from '~/utils/questions/locationSlug'; import useDefaultCompany from '~/utils/questions/useDefaultCompany'; import useDefaultLocation from '~/utils/questions/useDefaultLocation'; @@ -12,6 +14,8 @@ import type { FilterChoice } from './filter/FilterSection'; import CompanyTypeahead from './typeahead/CompanyTypeahead'; import LocationTypeahead from './typeahead/LocationTypeahead'; +import type { Location } from '~/types/questions'; + export type LandingQueryData = { companySlug: string; location: string; @@ -31,9 +35,9 @@ export default function LandingComponent({ const [company, setCompany] = useState( defaultCompany, ); - const [location, setLocation] = useState( - defaultLocation, - ); + const [location, setLocation] = useState< + (Location & TypeaheadOption) | undefined + >(defaultLocation); const [questionType, setQuestionType] = useState('CODING'); @@ -42,7 +46,7 @@ export default function LandingComponent({ setCompany(newCompany); }; - const handleChangeLocation = (newLocation: FilterChoice) => { + const handleChangeLocation = (newLocation: Location & TypeaheadOption) => { setLocation(newLocation); }; @@ -126,7 +130,7 @@ export default function LandingComponent({ if (company !== undefined && location !== undefined) { return handleLandingQuery({ companySlug: companyOptionToSlug(company), - location: location.value, + location: locationOptionToSlug(location), questionType, }); } diff --git a/apps/portal/src/pages/questions/browse.tsx b/apps/portal/src/pages/questions/browse.tsx index c08e189e..61196263 100644 --- a/apps/portal/src/pages/questions/browse.tsx +++ b/apps/portal/src/pages/questions/browse.tsx @@ -18,14 +18,11 @@ import LocationTypeahead from '~/components/questions/typeahead/LocationTypeahea import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead'; import { JobTitleLabels } from '~/components/shared/JobTitles'; -import { - companyOptionToSlug, - slugToCompanyOption, -} from '~/utils/questions/companySlug'; import type { QuestionAge } from '~/utils/questions/constants'; import { APP_TITLE } from '~/utils/questions/constants'; import { QUESTION_AGES, QUESTION_TYPES } from '~/utils/questions/constants'; import createSlug from '~/utils/questions/createSlug'; +import { locationOptionToSlug } from '~/utils/questions/locationSlug'; import relabelQuestionAggregates from '~/utils/questions/relabelQuestionAggregates'; import { useSearchParam, @@ -37,17 +34,6 @@ import type { Location } from '~/types/questions.d'; import { SortType } from '~/types/questions.d'; import { SortOrder } from '~/types/questions.d'; -function locationToSlug(value: Location & TypeaheadOption): string { - return [ - value.countryId, - value.stateId, - value.cityId, - value.id, - value.label, - value.value, - ].join('-'); -} - export default function QuestionsBrowsePage() { const router = useRouter(); @@ -90,7 +76,7 @@ export default function QuestionsBrowsePage() { useSearchParam('roles'); const [selectedLocations, setSelectedLocations, areLocationsInitialized] = useSearchParam('locations', { - paramToString: locationToSlug, + paramToString: locationOptionToSlug, stringToParam: (param) => { const [countryId, stateId, cityId, id, label, value] = param.split('-'); return { cityId, countryId, id, label, stateId, value }; @@ -267,7 +253,7 @@ export default function QuestionsBrowsePage() { pathname, query: { companies: selectedCompanySlugs, - locations: selectedLocations.map(locationToSlug), + locations: selectedLocations.map(locationOptionToSlug), questionAge: selectedQuestionAge, questionTypes: selectedQuestionTypes, roles: selectedRoles, @@ -292,7 +278,15 @@ export default function QuestionsBrowsePage() { ]); const selectedCompanyOptions = useMemo(() => { - return selectedCompanySlugs.map(slugToCompanyOption); + return selectedCompanySlugs.map((company) => { + const [id, label] = company.split('_'); + return { + checked: true, + id, + label, + value: id, + }; + }); }, [selectedCompanySlugs]); const selectedRoleOptions = useMemo(() => { @@ -359,12 +353,12 @@ export default function QuestionsBrowsePage() { if (option.checked) { setSelectedCompanySlugs([ ...selectedCompanySlugs, - companyOptionToSlug(option), + `${option.id}_${option.label}`, ]); } else { setSelectedCompanySlugs( selectedCompanySlugs.filter( - (companySlug) => companySlug !== companyOptionToSlug(option), + (companySlug) => companySlug !== `${option.id}_${option.label}`, ), ); } diff --git a/apps/portal/src/server/router/questions/questions-question-router.ts b/apps/portal/src/server/router/questions/questions-question-router.ts index a5c06f2d..a6821fb2 100644 --- a/apps/portal/src/server/router/questions/questions-question-router.ts +++ b/apps/portal/src/server/router/questions/questions-question-router.ts @@ -13,6 +13,7 @@ export const questionsQuestionRouter = createRouter() input: z.object({ cityIds: z.string().array(), companyIds: z.string().array(), + content: z.string().optional(), countryIds: z.string().array(), cursor: z.string().nullish(), endDate: z.date().default(new Date()), diff --git a/apps/portal/src/utils/questions/locationSlug.ts b/apps/portal/src/utils/questions/locationSlug.ts new file mode 100644 index 00000000..ad450ce0 --- /dev/null +++ b/apps/portal/src/utils/questions/locationSlug.ts @@ -0,0 +1,16 @@ +import type { TypeaheadOption } from '@tih/ui'; + +import type { Location } from '~/types/questions'; + +export function locationOptionToSlug( + value: Location & TypeaheadOption, +): string { + return [ + value.countryId, + value.stateId, + value.cityId, + value.id, + value.label, + value.value, + ].join('-'); +} From 410053425c0b2f343e6b04ce6f6485eda41b0082 Mon Sep 17 00:00:00 2001 From: Jeff Sieu Date: Mon, 31 Oct 2022 18:09:54 +0800 Subject: [PATCH 07/33] [questions][fix] fix typeahead spasm (#483) --- .../questions/forms/CreateQuestionEncounterForm.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx b/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx index 7a4f283e..b346b7b4 100644 --- a/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx +++ b/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx @@ -47,8 +47,9 @@ export default function CreateQuestionEncounterForm({
{ setSelectedCompany(company); @@ -64,8 +65,8 @@ export default function CreateQuestionEncounterForm({
{ setSelectedLocation(location); @@ -81,8 +82,8 @@ export default function CreateQuestionEncounterForm({
{ setSelectedRole(role); From 2c94691b07ecade1ea2152c9fdfb69eaedf27c83 Mon Sep 17 00:00:00 2001 From: Jeff Sieu Date: Mon, 31 Oct 2022 18:10:10 +0800 Subject: [PATCH 08/33] [questions][ui] show newlines in question post (#484) --- .../components/questions/card/question/BaseQuestionCard.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx b/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx index 0c8f1460..65a13054 100644 --- a/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx +++ b/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx @@ -216,7 +216,11 @@ export default function BaseQuestionCard({ /> )}
-

+

{content}

{!showReceivedForm && From e8aa1c9fdafffa039a2f5be2ec795743e5dbf35c Mon Sep 17 00:00:00 2001 From: Yangshun Tay Date: Mon, 31 Oct 2022 18:21:49 +0800 Subject: [PATCH 09/33] [portal][feat] custom login page (#485) --- .../portal/src/components/global/AppShell.tsx | 21 +++--- .../src/components/global/HomeNavigation.ts | 31 ++++---- .../offers/profile/ProfileComments.tsx | 3 +- .../comment/ResumeCommentVoteButtons.tsx | 3 +- .../resumes/shared/ResumeSignInButton.tsx | 18 +++-- .../components/shared/icons/GitHubIcon.tsx | 15 ++++ .../src/components/shared/loginPageHref.ts | 8 +++ apps/portal/src/pages/login.tsx | 72 +++++++++++++++++++ apps/portal/src/pages/resumes/[resumeId].tsx | 7 +- apps/portal/src/pages/resumes/index.tsx | 3 +- apps/portal/src/pages/resumes/submit.tsx | 3 +- 11 files changed, 139 insertions(+), 45 deletions(-) create mode 100644 apps/portal/src/components/shared/icons/GitHubIcon.tsx create mode 100644 apps/portal/src/components/shared/loginPageHref.ts create mode 100644 apps/portal/src/pages/login.tsx diff --git a/apps/portal/src/components/global/AppShell.tsx b/apps/portal/src/components/global/AppShell.tsx index 3c36e0d9..a0a44b84 100644 --- a/apps/portal/src/components/global/AppShell.tsx +++ b/apps/portal/src/components/global/AppShell.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import Link from 'next/link'; import { useRouter } from 'next/router'; -import { signIn, signOut, useSession } from 'next-auth/react'; +import { signOut, useSession } from 'next-auth/react'; import type { ReactNode } from 'react'; import { Fragment, useState } from 'react'; import { Menu, Transition } from '@headlessui/react'; @@ -19,12 +19,14 @@ import GoogleAnalytics from './GoogleAnalytics'; import MobileNavigation from './MobileNavigation'; import type { ProductNavigationItems } from './ProductNavigation'; import ProductNavigation from './ProductNavigation'; +import loginPageHref from '../shared/loginPageHref'; type Props = Readonly<{ children: ReactNode; }>; function ProfileJewel() { + const router = useRouter(); const { data: session, status } = useSession(); const isSessionLoading = status === 'loading'; @@ -32,25 +34,20 @@ function ProfileJewel() { return null; } + const loginHref = loginPageHref(); if (session == null) { - return ( - { - event.preventDefault(); - signIn(); - }}> - Sign in + return router.pathname !== loginHref.pathname ? ( + + Log In - ); + ) : null; } const userNavigation = [ { href: '/profile', name: 'Profile' }, { href: '/api/auth/signout', - name: 'Sign out', + name: 'Log out', onClick: (event: MouseEvent) => { event.preventDefault(); signOut(); diff --git a/apps/portal/src/components/global/HomeNavigation.ts b/apps/portal/src/components/global/HomeNavigation.ts index 96739432..d9316ee3 100644 --- a/apps/portal/src/components/global/HomeNavigation.ts +++ b/apps/portal/src/components/global/HomeNavigation.ts @@ -1,22 +1,21 @@ -import type { ProductNavigationItems } from '~/components/global/ProductNavigation'; - -const navigation: ProductNavigationItems = [ - { href: '/offers', name: 'Offers' }, - { href: '/questions', name: 'Question Bank' }, - { - children: [ - { href: '/resumes', name: 'View Resumes' }, - { href: '/resumes/submit', name: 'Submit Resume' }, - ], - href: '#', - name: 'Resumes', - }, -]; +// Not using this for now. +// const navigation: ProductNavigationItems = [ +// { href: '/offers', name: 'Offers' }, +// { href: '/questions', name: 'Question Bank' }, +// { +// children: [ +// { href: '/resumes', name: 'View Resumes' }, +// { href: '/resumes/submit', name: 'Submit Resume' }, +// ], +// href: '#', +// name: 'Resumes', +// }, +// ]; const config = { googleAnalyticsMeasurementID: 'G-DBLZDQ2ZZN', - navigation, - showGlobalNav: true, + navigation: [], + showGlobalNav: false, title: 'Tech Interview Handbook', titleHref: '/', }; diff --git a/apps/portal/src/components/offers/profile/ProfileComments.tsx b/apps/portal/src/components/offers/profile/ProfileComments.tsx index 70e388c7..44181afa 100644 --- a/apps/portal/src/components/offers/profile/ProfileComments.tsx +++ b/apps/portal/src/components/offers/profile/ProfileComments.tsx @@ -12,6 +12,7 @@ import { import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics'; import ExpandableCommentCard from '~/components/offers/profile/comments/ExpandableCommentCard'; import Tooltip from '~/components/offers/util/Tooltip'; +import loginPageHref from '~/components/shared/loginPageHref'; import { copyProfileLink } from '~/utils/offers/link'; import { trpc } from '~/utils/trpc'; @@ -195,7 +196,7 @@ export default function ProfileComments({
+ ))} +
+
+
+
+ ); +} diff --git a/apps/portal/src/pages/resumes/[resumeId].tsx b/apps/portal/src/pages/resumes/[resumeId].tsx index 3c0604b4..4e6c9bea 100644 --- a/apps/portal/src/pages/resumes/[resumeId].tsx +++ b/apps/portal/src/pages/resumes/[resumeId].tsx @@ -22,6 +22,7 @@ import ResumeCommentsForm from '~/components/resumes/comments/ResumeCommentsForm import ResumeCommentsList from '~/components/resumes/comments/ResumeCommentsList'; import ResumePdf from '~/components/resumes/ResumePdf'; import ResumeExpandableText from '~/components/resumes/shared/ResumeExpandableText'; +import loginPageHref from '~/components/shared/loginPageHref'; import type { ExperienceFilter, @@ -107,7 +108,7 @@ export default function ResumeReviewPage() { const onStarButtonClick = () => { if (session?.user?.id == null) { - router.push('/api/auth/signin'); + router.push(loginPageHref()); return; } @@ -184,8 +185,8 @@ export default function ResumeReviewPage() {
diff --git a/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx b/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx index 65a13054..7b50c1a9 100644 --- a/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx +++ b/apps/portal/src/components/questions/card/question/BaseQuestionCard.tsx @@ -218,7 +218,7 @@ export default function BaseQuestionCard({

{content} diff --git a/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx b/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx index b346b7b4..5e5f67c4 100644 --- a/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx +++ b/apps/portal/src/components/questions/forms/CreateQuestionEncounterForm.tsx @@ -42,7 +42,9 @@ export default function CreateQuestionEncounterForm({ return (

-

I saw this question at

+

+ I saw this question {step <= 1 ? 'at' : step === 2 ? 'for' : 'on'} +

{step === 0 && (
cityId) .filter((id) => id !== undefined) as Array, companyIds: selectedCompanySlugs.map((slug) => slug.split('_')[0]), + content: query, countryIds: [], endDate: today, limit: 10, @@ -475,8 +478,8 @@ export default function QuestionsBrowsePage() {
-
-
+
+
{ const { cityId, countryId, stateId } = data.location; @@ -495,11 +498,15 @@ export default function QuestionsBrowsePage() {
{ setFilterDrawerOpen(!filterDrawerOpen); }} + onQueryChange={(newQuery) => { + setQuery(newQuery); + }} onSortOrderChange={setSortOrder} onSortTypeChange={setSortType} /> diff --git a/apps/portal/src/server/router/questions/questions-question-router.ts b/apps/portal/src/server/router/questions/questions-question-router.ts index a6821fb2..4d506b94 100644 --- a/apps/portal/src/server/router/questions/questions-question-router.ts +++ b/apps/portal/src/server/router/questions/questions-question-router.ts @@ -236,7 +236,8 @@ export const questionsQuestionRouter = createRouter() SELECT id FROM "QuestionsQuestion" WHERE to_tsvector("content") @@ to_tsquery('english', ${query}) - ORDER BY ts_rank_cd(to_tsvector("content"), to_tsquery('english', ${query}), 4) DESC; + ORDER BY ts_rank_cd(to_tsvector("content"), to_tsquery('english', ${query}), 4) DESC + LIMIT 3; `; const relatedQuestionsIdArray = relatedQuestionsId.map( @@ -281,4 +282,183 @@ export const questionsQuestionRouter = createRouter() return processedQuestionsData; }, + }) + .query('getQuestionsByFilterAndContent', { + input: z.object({ + cityIds: z.string().array(), + companyIds: z.string().array(), + content: z.string(), + countryIds: z.string().array(), + cursor: z.string().nullish(), + endDate: z.date().default(new Date()), + limit: z.number().min(1).default(50), + questionTypes: z.nativeEnum(QuestionsQuestionType).array(), + roles: z.string().array(), + sortOrder: z.nativeEnum(SortOrder), + sortType: z.nativeEnum(SortType), + startDate: z.date().optional(), + stateIds: z.string().array(), + }), + async resolve({ ctx, input }) { + const escapeChars = /[()|&:*!]/g; + + const query = input.content + .replace(escapeChars, ' ') + .trim() + .split(/\s+/) + .join(' | '); + + let relatedQuestionsId: Array<{ id: string }> = []; + + if (input.content !== "") { + relatedQuestionsId = await ctx.prisma + .$queryRaw` + SELECT id FROM "QuestionsQuestion" + WHERE + to_tsvector("content") @@ to_tsquery('english', ${query}) + ORDER BY ts_rank_cd(to_tsvector("content"), to_tsquery('english', ${query}), 4) DESC + LIMIT 3; + `; + } + + + + const relatedQuestionsIdArray = relatedQuestionsId.map( + (current) => current.id, + ); + + const { cursor } = input; + + const sortCondition = + input.sortType === SortType.TOP + ? [ + { + upvotes: input.sortOrder, + }, + { + id: input.sortOrder, + }, + ] + : [ + { + lastSeenAt: input.sortOrder, + }, + { + id: input.sortOrder, + }, + ]; + + const questionsData = await ctx.prisma.questionsQuestion.findMany({ + cursor: cursor ? { id: cursor } : undefined, + include: { + _count: { + select: { + answers: true, + comments: true, + }, + }, + encounters: { + select: { + city: true, + company: true, + country: true, + role: true, + seenAt: true, + state: true, + }, + }, + user: { + select: { + name: true, + }, + }, + votes: true, + }, + orderBy: sortCondition, + take: input.limit + 1, + where: { + id: input.content !== "" ? { + in: relatedQuestionsIdArray, + } : undefined, + ...(input.questionTypes.length > 0 + ? { + questionType: { + in: input.questionTypes, + }, + } + : {}), + encounters: { + some: { + seenAt: { + gte: input.startDate, + lte: input.endDate, + }, + ...(input.companyIds.length > 0 + ? { + company: { + id: { + in: input.companyIds, + }, + }, + } + : {}), + ...(input.cityIds.length > 0 + ? { + city: { + id: { + in: input.cityIds, + }, + }, + } + : {}), + ...(input.countryIds.length > 0 + ? { + country: { + id: { + in: input.countryIds, + }, + }, + } + : {}), + ...(input.stateIds.length > 0 + ? { + state: { + id: { + in: input.stateIds, + }, + }, + } + : {}), + ...(input.roles.length > 0 + ? { + role: { + in: input.roles, + }, + } + : {}), + }, + }, + }, + }); + + const processedQuestionsData = questionsData.map( + createQuestionWithAggregateData, + ); + + let nextCursor: typeof cursor | undefined = undefined; + + if (questionsData.length > input.limit) { + const nextItem = questionsData.pop()!; + processedQuestionsData.pop(); + + const nextIdCursor: string | undefined = nextItem.id; + + nextCursor = nextIdCursor; + } + + return { + data: processedQuestionsData, + nextCursor, + }; + }, }); From fcff0d663fbc626f5ee83acb037b6117fc7c99c0 Mon Sep 17 00:00:00 2001 From: Tay Yang Shun Date: Mon, 31 Oct 2022 20:09:49 +0800 Subject: [PATCH 13/33] [portal][misc] fix incorrect TODO --- apps/portal/src/pages/questions/browse.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/portal/src/pages/questions/browse.tsx b/apps/portal/src/pages/questions/browse.tsx index c76b6213..40a9c00c 100644 --- a/apps/portal/src/pages/questions/browse.tsx +++ b/apps/portal/src/pages/questions/browse.tsx @@ -446,7 +446,7 @@ export default function QuestionsBrowsePage() { isLabelHidden={true} placeholder="Search locations" onSelect={(option) => { - // @ts-ignore TODO(offers): fix potentially empty value. + // @ts-ignore TODO(questions): handle potentially null value. onOptionChange({ ...option, checked: true, From 1acb37939cbfadcc67db8d5ad06477b25d5448bd Mon Sep 17 00:00:00 2001 From: Tay Yang Shun Date: Mon, 31 Oct 2022 20:24:07 +0800 Subject: [PATCH 14/33] [portal][misc] refactor typeahead props --- .../src/components/shared/CitiesTypeahead.tsx | 38 +++++++++---------- .../components/shared/CompaniesTypeahead.tsx | 36 +++++++++--------- .../components/shared/CountriesTypeahead.tsx | 36 +++++++++--------- .../components/shared/JobTitlesTypahead.tsx | 35 ++++++++--------- 4 files changed, 73 insertions(+), 72 deletions(-) diff --git a/apps/portal/src/components/shared/CitiesTypeahead.tsx b/apps/portal/src/components/shared/CitiesTypeahead.tsx index 05e527ca..902759b0 100644 --- a/apps/portal/src/components/shared/CitiesTypeahead.tsx +++ b/apps/portal/src/components/shared/CitiesTypeahead.tsx @@ -1,28 +1,32 @@ +import type { ComponentProps } from 'react'; import { useState } from 'react'; import type { TypeaheadOption } from '@tih/ui'; import { Typeahead } from '@tih/ui'; import { trpc } from '~/utils/trpc'; -type Props = Readonly<{ - disabled?: boolean; - errorMessage?: string; - isLabelHidden?: boolean; - label?: string; - onSelect: (option: TypeaheadOption | null) => void; - placeholder?: string; - required?: boolean; - value?: TypeaheadOption | null; -}>; +type BaseProps = Pick< + ComponentProps, + | 'disabled' + | 'errorMessage' + | 'isLabelHidden' + | 'placeholder' + | 'required' + | 'textSize' +>; + +type Props = BaseProps & + Readonly<{ + label?: string; + onSelect: (option: TypeaheadOption | null) => void; + value?: TypeaheadOption | null; + }>; export default function CitiesTypeahead({ - disabled, label = 'City', onSelect, - isLabelHidden, - placeholder, - required, value, + ...props }: Props) { const [query, setQuery] = useState(''); const cities = trpc.useQuery([ @@ -36,8 +40,6 @@ export default function CitiesTypeahead({ return ( ); } diff --git a/apps/portal/src/components/shared/CompaniesTypeahead.tsx b/apps/portal/src/components/shared/CompaniesTypeahead.tsx index 619d9a55..76d35557 100644 --- a/apps/portal/src/components/shared/CompaniesTypeahead.tsx +++ b/apps/portal/src/components/shared/CompaniesTypeahead.tsx @@ -1,26 +1,30 @@ +import type { ComponentProps } from 'react'; import { useState } from 'react'; import type { TypeaheadOption } from '@tih/ui'; import { Typeahead } from '@tih/ui'; import { trpc } from '~/utils/trpc'; -type Props = Readonly<{ - disabled?: boolean; - errorMessage?: string; - isLabelHidden?: boolean; - onSelect: (option: TypeaheadOption | null) => void; - placeholder?: string; - required?: boolean; - value?: TypeaheadOption | null; -}>; +type BaseProps = Pick< + ComponentProps, + | 'disabled' + | 'errorMessage' + | 'isLabelHidden' + | 'placeholder' + | 'required' + | 'textSize' +>; + +type Props = BaseProps & + Readonly<{ + onSelect: (option: TypeaheadOption | null) => void; + value?: TypeaheadOption | null; + }>; export default function CompaniesTypeahead({ - disabled, onSelect, - isLabelHidden, - placeholder, - required, value, + ...props }: Props) { const [query, setQuery] = useState(''); const companies = trpc.useQuery([ @@ -34,8 +38,6 @@ export default function CompaniesTypeahead({ return ( ); } diff --git a/apps/portal/src/components/shared/CountriesTypeahead.tsx b/apps/portal/src/components/shared/CountriesTypeahead.tsx index c3bae569..51d72cb0 100644 --- a/apps/portal/src/components/shared/CountriesTypeahead.tsx +++ b/apps/portal/src/components/shared/CountriesTypeahead.tsx @@ -1,26 +1,30 @@ +import type { ComponentProps } from 'react'; import { useState } from 'react'; import type { TypeaheadOption } from '@tih/ui'; import { Typeahead } from '@tih/ui'; import { trpc } from '~/utils/trpc'; -type Props = Readonly<{ - disabled?: boolean; - errorMessage?: string; - isLabelHidden?: boolean; - onSelect: (option: TypeaheadOption | null) => void; - placeholder?: string; - required?: boolean; - value?: TypeaheadOption | null; -}>; +type BaseProps = Pick< + ComponentProps, + | 'disabled' + | 'errorMessage' + | 'isLabelHidden' + | 'placeholder' + | 'required' + | 'textSize' +>; + +type Props = BaseProps & + Readonly<{ + onSelect: (option: TypeaheadOption | null) => void; + value?: TypeaheadOption | null; + }>; export default function CountriesTypeahead({ - disabled, onSelect, - isLabelHidden, - placeholder, - required, value, + ...props }: Props) { const [query, setQuery] = useState(''); const countries = trpc.useQuery([ @@ -34,8 +38,6 @@ export default function CountriesTypeahead({ return ( ); } diff --git a/apps/portal/src/components/shared/JobTitlesTypahead.tsx b/apps/portal/src/components/shared/JobTitlesTypahead.tsx index b5221262..9de68c45 100644 --- a/apps/portal/src/components/shared/JobTitlesTypahead.tsx +++ b/apps/portal/src/components/shared/JobTitlesTypahead.tsx @@ -1,25 +1,30 @@ +import type { ComponentProps } from 'react'; import { useState } from 'react'; import type { TypeaheadOption } from '@tih/ui'; import { Typeahead } from '@tih/ui'; import { JobTitleLabels } from './JobTitles'; -type Props = Readonly<{ - disabled?: boolean; - isLabelHidden?: boolean; - onSelect: (option: TypeaheadOption | null) => void; - placeholder?: string; - required?: boolean; - value?: TypeaheadOption | null; -}>; +type BaseProps = Pick< + ComponentProps, + | 'disabled' + | 'errorMessage' + | 'isLabelHidden' + | 'placeholder' + | 'required' + | 'textSize' +>; + +type Props = BaseProps & + Readonly<{ + onSelect: (option: TypeaheadOption | null) => void; + value?: TypeaheadOption | null; + }>; export default function JobTitlesTypeahead({ - disabled, onSelect, - isLabelHidden, - placeholder, - required, value, + ...props }: Props) { const [query, setQuery] = useState(''); const options = Object.entries(JobTitleLabels) @@ -35,18 +40,14 @@ export default function JobTitlesTypeahead({ return ( ); } From 64bc8158c12d1d48b96bddb640caab38ca110f8c Mon Sep 17 00:00:00 2001 From: Yangshun Tay Date: Tue, 1 Nov 2022 11:11:10 +0800 Subject: [PATCH 15/33] [offers][fix] tweak submit offer job type selector (#487) --- .../src/components/offers/JobTypeTabs.tsx | 50 +++++++++++++++++++ .../submissionForm/OfferDetailsForm.tsx | 43 +++++----------- apps/portal/src/pages/offers/index.tsx | 2 + packages/ui/src/Tabs/Tabs.tsx | 2 +- 4 files changed, 66 insertions(+), 31 deletions(-) create mode 100644 apps/portal/src/components/offers/JobTypeTabs.tsx diff --git a/apps/portal/src/components/offers/JobTypeTabs.tsx b/apps/portal/src/components/offers/JobTypeTabs.tsx new file mode 100644 index 00000000..8ea87bc6 --- /dev/null +++ b/apps/portal/src/components/offers/JobTypeTabs.tsx @@ -0,0 +1,50 @@ +import clsx from 'clsx'; +import { JobType } from '@prisma/client'; + +import { JobTypeLabel } from './types'; + +type Props = Readonly<{ + onChange: (jobType: JobType) => void; + value: JobType; +}>; + +const tabs = [ + { + label: JobTypeLabel.FULLTIME, + value: JobType.FULLTIME, + }, + { + label: JobTypeLabel.INTERN, + value: JobType.INTERN, + }, +]; + +export default function JobTypeTabs({ value, onChange }: Props) { + return ( +
+ +
+ ); +} diff --git a/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx b/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx index 63abe7d1..34a65829 100644 --- a/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx +++ b/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx @@ -32,6 +32,7 @@ import FormMonthYearPicker from '../../forms/FormMonthYearPicker'; import FormSelect from '../../forms/FormSelect'; import FormTextArea from '../../forms/FormTextArea'; import FormTextInput from '../../forms/FormTextInput'; +import JobTypeTabs from '../../JobTypeTabs'; import type { OfferFormData } from '../../types'; import { JobTypeLabel } from '../../types'; import { @@ -103,7 +104,7 @@ function FullTimeOfferDetailsForm({ })} />
-
+
Fill in your offer details -
-
-
-
-
+
+ { + if (newJobType === jobType) { + return; + } + + setDialogOpen(true); + }} + />
{ if (option) { setjobTitleFilter(option.value); @@ -56,6 +57,7 @@ export default function OffersHomePage() { { if (option) { setCompanyFilter(option.value); diff --git a/packages/ui/src/Tabs/Tabs.tsx b/packages/ui/src/Tabs/Tabs.tsx index ac34722e..d387424b 100644 --- a/packages/ui/src/Tabs/Tabs.tsx +++ b/packages/ui/src/Tabs/Tabs.tsx @@ -28,7 +28,7 @@ export default function Tabs({ label, tabs, value, onChange }: Props) { children: tab.label, className: clsx( isSelected - ? 'bg-indigo-100 text-indigo-700' + ? 'bg-primary-100 text-primary-700' : 'hover:bg-slate-100 text-slate-500 hover:text-slate-700', 'px-3 py-2 font-medium text-sm rounded-md', ), From 21c9d9410a5fa127c6903ef559ed7829a11ada81 Mon Sep 17 00:00:00 2001 From: Yangshun Tay Date: Tue, 1 Nov 2022 21:17:18 +0800 Subject: [PATCH 16/33] [offers][feat] tweak offer details submission form (#488) --- .../offersSubmission/OffersSubmissionForm.tsx | 7 +- .../submissionForm/OfferDetailsForm.tsx | 576 +++++++++--------- .../HorizontalDivider/HorizontalDivider.tsx | 2 +- 3 files changed, 301 insertions(+), 284 deletions(-) diff --git a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx index 325c9afc..440e2686 100644 --- a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx +++ b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx @@ -275,16 +275,17 @@ export default function OffersSubmissionForm({ />
-
+ {steps[step]} - {/*
{JSON.stringify(formMethods.watch(), null, 2)}
*/} {step === 0 && (
+
+
+ + + } + endAddOnType="element" + errorMessage={ + offerFields?.offersFullTime?.totalCompensation?.value?.message + } + label="Total Compensation (Annual)" + placeholder="0" + required={true} + startAddOn="$" + startAddOnType="label" + type="number" + {...register( + `offers.${index}.offersFullTime.totalCompensation.value`, + { + min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, + required: FieldError.REQUIRED, + valueAsNumber: true, + }, + )} + /> +
+
+ + } + endAddOnType="element" + errorMessage={ + offerFields?.offersFullTime?.baseSalary?.value?.message + } + label="Base Salary (Annual)" + placeholder="0" + startAddOn="$" + startAddOnType="label" + type="number" + {...register(`offers.${index}.offersFullTime.baseSalary.value`, { + min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, valueAsNumber: true, - }, - )} - /> -
-
- - } - endAddOnType="element" - errorMessage={offerFields?.offersFullTime?.baseSalary?.value?.message} - label="Base Salary (Annual)" - placeholder="0" - startAddOn="$" - startAddOnType="label" - type="number" - {...register(`offers.${index}.offersFullTime.baseSalary.value`, { - min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, - valueAsNumber: true, - })} - /> - - } - endAddOnType="element" - errorMessage={offerFields?.offersFullTime?.bonus?.value?.message} - label="Bonus (Annual)" - placeholder="0" - startAddOn="$" - startAddOnType="label" - type="number" - {...register(`offers.${index}.offersFullTime.bonus.value`, { - min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, - valueAsNumber: true, - })} - /> -
-
- - } - endAddOnType="element" - errorMessage={offerFields?.offersFullTime?.stocks?.value?.message} - label="Stocks (Annual)" - placeholder="0" - startAddOn="$" - startAddOnType="label" - type="number" - {...register(`offers.${index}.offersFullTime.stocks.value`, { - min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, - valueAsNumber: true, - })} - /> -
-
+ })} + /> + + } + endAddOnType="element" + errorMessage={offerFields?.offersFullTime?.bonus?.value?.message} + label="Bonus (Annual)" + placeholder="0" + startAddOn="$" + startAddOnType="label" + type="number" + {...register(`offers.${index}.offersFullTime.bonus.value`, { + min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, + valueAsNumber: true, + })} + /> + + } + endAddOnType="element" + errorMessage={offerFields?.offersFullTime?.stocks?.value?.message} + label="Stocks (Annual)" + placeholder="0" + startAddOn="$" + startAddOnType="label" + type="number" + {...register(`offers.${index}.offersFullTime.stocks.value`, { + min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, + valueAsNumber: true, + })} + /> +
+
+
-
-
-
-
{index > 0 && ( -
+
)} -
+
); } @@ -308,26 +326,23 @@ function InternshipOfferDetailsForm({ }); return ( -
-
-
- { - if (option) { - setValue(`offers.${index}.offersIntern.title`, option.value); - } - }} - /> -
-
-
-
+
+
+ { + if (option) { + setValue(`offers.${index}.offersIntern.title`, option.value); + } + }} + /> + +
+
- -
-
- - -
-
- -
-
- - } - endAddOnType="element" - errorMessage={ - offerFields?.offersIntern?.monthlySalary?.value?.message - } - label="Salary (Monthly)" - placeholder="0" - required={true} - startAddOn="$" - startAddOnType="label" - type="number" - {...register(`offers.${index}.offersIntern.monthlySalary.value`, { - min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, - required: FieldError.REQUIRED, - valueAsNumber: true, - })} - /> -
-
+
+ + +
+ +
+
+ + + } + endAddOnType="element" + errorMessage={ + offerFields?.offersIntern?.monthlySalary?.value?.message + } + label="Salary (Monthly)" + placeholder="0" + required={true} + startAddOn="$" + startAddOnType="label" + type="number" + {...register(`offers.${index}.offersIntern.monthlySalary.value`, { + min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 }, + required: FieldError.REQUIRED, + valueAsNumber: true, + })} + /> +
+
+
-
-
-
-
- {index > 0 && ( -
+ + {index > 0 && ( +
+ +
+
+
+ )}
); } @@ -466,7 +482,7 @@ function OfferDetailsFormArray({ const { append, remove, fields } = fieldArrayValues; return ( -
+
{fields.map((item, index) => { return (
@@ -483,7 +499,7 @@ function OfferDetailsFormArray({ icon={PlusIcon} label="Add another offer" size="lg" - variant="tertiary" + variant="secondary" onClick={() => append( jobType === JobType.FULLTIME @@ -524,7 +540,7 @@ export default function OfferDetailsForm({ jobType === JobType.FULLTIME ? JobTypeLabel.INTERN : JobTypeLabel.FULLTIME; return ( -
+
Fill in your offer details
diff --git a/packages/ui/src/HorizontalDivider/HorizontalDivider.tsx b/packages/ui/src/HorizontalDivider/HorizontalDivider.tsx index 6e2396dc..c9f3d2b1 100644 --- a/packages/ui/src/HorizontalDivider/HorizontalDivider.tsx +++ b/packages/ui/src/HorizontalDivider/HorizontalDivider.tsx @@ -8,7 +8,7 @@ export default function HorizontalDivider({ className }: Props) { return (
); } From 6682d81d2e624a98b3b268ab3aca5d90cf7b9349 Mon Sep 17 00:00:00 2001 From: Zhang Ziqing <69516975+ziqing26@users.noreply.github.com> Date: Wed, 2 Nov 2022 04:03:34 +0800 Subject: [PATCH 17/33] [offers][fix] fix profile page mobile compatible style (#489) * [offers][fix] fix offer profile page mobile compatibility * [offers][style] style profile offer card --- .../components/offers/profile/OfferCard.tsx | 2 +- .../offers/profile/ProfileComments.tsx | 201 +++++++++--------- .../offers/profile/ProfileHeader.tsx | 89 ++++---- .../src/components/offers/table/OffersRow.tsx | 2 +- .../components/offers/table/OffersTable.tsx | 4 +- .../offers/table/OffersTablePagination.tsx | 53 +++-- apps/portal/src/pages/offers/dashboard.tsx | 6 +- .../pages/offers/profile/[offerProfileId].tsx | 26 +-- 8 files changed, 201 insertions(+), 182 deletions(-) diff --git a/apps/portal/src/components/offers/profile/OfferCard.tsx b/apps/portal/src/components/offers/profile/OfferCard.tsx index 6d02f134..5e5df4c4 100644 --- a/apps/portal/src/components/offers/profile/OfferCard.tsx +++ b/apps/portal/src/components/offers/profile/OfferCard.tsx @@ -128,7 +128,7 @@ export default function OfferCard({ ); } return ( -
+
diff --git a/apps/portal/src/components/offers/profile/ProfileComments.tsx b/apps/portal/src/components/offers/profile/ProfileComments.tsx index 44181afa..6a1d85a4 100644 --- a/apps/portal/src/components/offers/profile/ProfileComments.tsx +++ b/apps/portal/src/components/offers/profile/ProfileComments.tsx @@ -110,108 +110,115 @@ export default function ProfileComments({ ); } return ( -
-
- {isEditable && ( - -
+
+ +
+
+
+ +

Discussions

+ {isEditable || session?.user?.name ? ( +
+