From ef6179361667cc6bb060fa748c376c864d4366f7 Mon Sep 17 00:00:00 2001 From: Ai Ling <50992674+ailing35@users.noreply.github.com> Date: Tue, 25 Oct 2022 03:31:46 +0800 Subject: [PATCH] [offers][fix] Fix offers form experience section (#427) --- .../offersSubmission/OffersProfileSave.tsx | 17 +- .../OffersSubmissionAnalysis.tsx | 49 ++++++ .../offersSubmission/OffersSubmissionForm.tsx | 52 +++---- .../submissionForm/BackgroundForm.tsx | 20 +-- .../offers/profile/edit/[offerProfileId].tsx | 12 +- .../router/offers/offers-profile-router.ts | 147 +++++++++--------- apps/portal/src/utils/offers/form.tsx | 27 ++++ 7 files changed, 188 insertions(+), 136 deletions(-) create mode 100644 apps/portal/src/components/offers/offersSubmission/OffersSubmissionAnalysis.tsx diff --git a/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx b/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx index 03c77dc9..26d358a4 100644 --- a/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx +++ b/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx @@ -1,15 +1,9 @@ -import { useRouter } from 'next/router'; // Import { useState } from 'react'; // import { setTimeout } from 'timers'; import { DocumentDuplicateIcon } from '@heroicons/react/20/solid'; -import { EyeIcon } from '@heroicons/react/24/outline'; import { Button, TextInput, useToast } from '@tih/ui'; -import { - copyProfileLink, - getProfileLink, - getProfilePath, -} from '~/utils/offers/link'; +import { copyProfileLink, getProfileLink } from '~/utils/offers/link'; type OfferProfileSaveProps = Readonly<{ profileId: string; @@ -23,7 +17,6 @@ export default function OffersProfileSave({ const { showToast } = useToast(); // Const [isSaving, setSaving] = useState(false); // const [isSaved, setSaved] = useState(false); - const router = useRouter(); // Const saveProfile = () => { // setSaving(true); @@ -82,14 +75,6 @@ export default function OffersProfileSave({ onClick={saveProfile} /> */} -
-
); diff --git a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionAnalysis.tsx b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionAnalysis.tsx new file mode 100644 index 00000000..325cbae0 --- /dev/null +++ b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionAnalysis.tsx @@ -0,0 +1,49 @@ +import { useRouter } from 'next/router'; +import { EyeIcon } from '@heroicons/react/24/outline'; + +import { Button } from '~/../../../packages/ui/dist'; +import { getProfilePath } from '~/utils/offers/link'; + +import OfferAnalysis from '../offerAnalysis/OfferAnalysis'; + +import type { ProfileAnalysis } from '~/types/offers'; + +type Props = Readonly<{ + analysis?: ProfileAnalysis | null; + isError: boolean; + isLoading: boolean; + profileId?: string; + token?: string; +}>; + +export default function OffersSubmissionAnalysis({ + analysis, + isError, + isLoading, + profileId = '', + token = '', +}: Props) { + const router = useRouter(); + + return ( +
+
+ Result +
+ +
+
+
+ ); +} diff --git a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx index 39544921..55f2f756 100644 --- a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx +++ b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx @@ -15,16 +15,17 @@ import type { } from '~/components/offers/types'; import type { Month } from '~/components/shared/MonthYearPicker'; -import { cleanObject, removeInvalidMoneyData } from '~/utils/offers/form'; +import { + cleanObject, + removeEmptyObjects, + removeInvalidMoneyData, +} from '~/utils/offers/form'; import { getCurrentMonth, getCurrentYear } from '~/utils/offers/time'; import { trpc } from '~/utils/trpc'; -import OfferAnalysis from '../offerAnalysis/OfferAnalysis'; +import OffersSubmissionAnalysis from './OffersSubmissionAnalysis'; -import type { - CreateOfferProfileResponse, - ProfileAnalysis, -} from '~/types/offers'; +import type { ProfileAnalysis } from '~/types/offers'; const defaultOfferValues = { comments: '', @@ -73,15 +74,12 @@ type Props = Readonly<{ export default function OffersSubmissionForm({ initialOfferProfileValues = defaultOfferProfileValues, - profileId, - token, + profileId: editProfileId = '', + token: editToken = '', }: Props) { const [formStep, setFormStep] = useState(0); - const [createProfileResponse, setCreateProfileResponse] = - useState({ - id: profileId || '', - token: token || '', - }); + const [profileId, setProfileId] = useState(editProfileId); + const [token, setToken] = useState(editToken); const [analysis, setAnalysis] = useState(null); const pageRef = useRef(null); @@ -125,11 +123,7 @@ export default function OffersSubmissionForm({ }, { component: ( - + ), hasNext: true, hasPrevious: false, @@ -137,17 +131,13 @@ export default function OffersSubmissionForm({ }, { component: ( -
-
- Result -
- -
+ ), hasNext: false, hasPrevious: true, @@ -184,7 +174,8 @@ export default function OffersSubmissionForm({ generateAnalysisMutation.mutate({ profileId: data?.id || '', }); - setCreateProfileResponse(data); + setProfileId(data.id); + setToken(data.token); setFormStep(formStep + 1); scrollToTop(); }, @@ -197,6 +188,7 @@ export default function OffersSubmissionForm({ } data = removeInvalidMoneyData(data); + data.offers = removeEmptyObjects(data.offers); const background = cleanObject(data.background); background.specificYoes = data.background.specificYoes.filter( diff --git a/apps/portal/src/components/offers/offersSubmission/submissionForm/BackgroundForm.tsx b/apps/portal/src/components/offers/offersSubmission/submissionForm/BackgroundForm.tsx index 8dcfae54..52d0a42e 100644 --- a/apps/portal/src/components/offers/offersSubmission/submissionForm/BackgroundForm.tsx +++ b/apps/portal/src/components/offers/offersSubmission/submissionForm/BackgroundForm.tsx @@ -18,7 +18,6 @@ import { CURRENCY_OPTIONS, } from '~/utils/offers/currency/CurrencyEnum'; -import FormMonthYearPicker from '../../forms/FormMonthYearPicker'; import FormRadioList from '../../forms/FormRadioList'; import FormSelect from '../../forms/FormSelect'; import FormTextInput from '../../forms/FormTextInput'; @@ -235,7 +234,6 @@ function InternshipJobFields() { function CurrentJobSection() { const { register } = useFormContext(); const watchJobType = useWatch({ - defaultValue: JobType.FULLTIME, name: 'background.experiences.0.jobType', }); @@ -247,7 +245,7 @@ function CurrentJobSection() {
-
- - -
diff --git a/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx b/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx index 2b9550ae..245c0bb5 100644 --- a/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx +++ b/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx @@ -34,7 +34,17 @@ export default function OffersEditPage() { experiences: experiences.length === 0 ? [{ jobType: JobType.FULLTIME }] - : experiences, + : experiences.map((exp) => ({ + companyId: exp.company?.id, + durationInMonths: exp.durationInMonths, + id: exp.id, + jobType: exp.jobType, + level: exp.level, + location: exp.location, + monthlySalary: exp.monthlySalary, + title: exp.title, + totalCompensation: exp.totalCompensation, + })), id, specificYoes, totalYoe, diff --git a/apps/portal/src/server/router/offers/offers-profile-router.ts b/apps/portal/src/server/router/offers/offers-profile-router.ts index bf86613a..f71d9c48 100644 --- a/apps/portal/src/server/router/offers/offers-profile-router.ts +++ b/apps/portal/src/server/router/offers/offers-profile-router.ts @@ -285,11 +285,7 @@ export const offersProfileRouter = createRouter() }, experiences: { create: input.background.experiences.map(async (x) => { - if ( - x.jobType === JobType.FULLTIME && - x.totalCompensation?.currency != null && - x.totalCompensation?.value != null - ) { + if (x.jobType === JobType.FULLTIME) { if (x.companyId) { return { company: { @@ -301,18 +297,21 @@ export const offersProfileRouter = createRouter() jobType: x.jobType, level: x.level, title: x.title, - totalCompensation: { - create: { - baseCurrency: baseCurrencyString, - baseValue: await convert( - x.totalCompensation.value, - x.totalCompensation.currency, - baseCurrencyString, - ), - currency: x.totalCompensation.currency, - value: x.totalCompensation.value, - }, - }, + totalCompensation: + x.totalCompensation != null + ? { + create: { + baseCurrency: baseCurrencyString, + baseValue: await convert( + x.totalCompensation.value, + x.totalCompensation.currency, + baseCurrencyString, + ), + currency: x.totalCompensation.currency, + value: x.totalCompensation.value, + }, + } + : undefined, }; } return { @@ -321,25 +320,24 @@ export const offersProfileRouter = createRouter() level: x.level, location: x.location, title: x.title, - totalCompensation: { - create: { - baseCurrency: baseCurrencyString, - baseValue: await convert( - x.totalCompensation.value, - x.totalCompensation.currency, - baseCurrencyString, - ), - currency: x.totalCompensation.currency, - value: x.totalCompensation.value, - }, - }, + totalCompensation: + x.totalCompensation != null + ? { + create: { + baseCurrency: baseCurrencyString, + baseValue: await convert( + x.totalCompensation.value, + x.totalCompensation.currency, + baseCurrencyString, + ), + currency: x.totalCompensation.currency, + value: x.totalCompensation.value, + }, + } + : undefined, }; } - if ( - x.jobType === JobType.INTERN && - x.monthlySalary?.currency != null && - x.monthlySalary?.value != null - ) { + if (x.jobType === JobType.INTERN) { if (x.companyId) { return { company: { @@ -349,36 +347,42 @@ export const offersProfileRouter = createRouter() }, durationInMonths: x.durationInMonths, jobType: x.jobType, - monthlySalary: { - create: { - baseCurrency: baseCurrencyString, - baseValue: await convert( - x.monthlySalary.value, - x.monthlySalary.currency, - baseCurrencyString, - ), - currency: x.monthlySalary.currency, - value: x.monthlySalary.value, - }, - }, + monthlySalary: + x.monthlySalary != null + ? { + create: { + baseCurrency: baseCurrencyString, + baseValue: await convert( + x.monthlySalary.value, + x.monthlySalary.currency, + baseCurrencyString, + ), + currency: x.monthlySalary.currency, + value: x.monthlySalary.value, + }, + } + : undefined, title: x.title, }; } return { durationInMonths: x.durationInMonths, jobType: x.jobType, - monthlySalary: { - create: { - baseCurrency: baseCurrencyString, - baseValue: await convert( - x.monthlySalary.value, - x.monthlySalary.currency, - baseCurrencyString, - ), - currency: x.monthlySalary.currency, - value: x.monthlySalary.value, - }, - }, + monthlySalary: + x.monthlySalary != null + ? { + create: { + baseCurrency: baseCurrencyString, + baseValue: await convert( + x.monthlySalary.value, + x.monthlySalary.currency, + baseCurrencyString, + ), + currency: x.monthlySalary.currency, + value: x.monthlySalary.value, + }, + } + : undefined, title: x.title, }; } @@ -710,6 +714,7 @@ export const offersProfileRouter = createRouter() data: { companyId: exp.companyId, // TODO: check if can change with connect or whether there is a difference durationInMonths: exp.durationInMonths, + jobType: exp.jobType as JobType, level: exp.level, }, where: { @@ -818,18 +823,20 @@ export const offersProfileRouter = createRouter() level: exp.level, location: exp.location, title: exp.title, - totalCompensation: { - create: { - baseCurrency: baseCurrencyString, - baseValue: await convert( - exp.totalCompensation.value, - exp.totalCompensation.currency, - baseCurrencyString, - ), - currency: exp.totalCompensation.currency, - value: exp.totalCompensation.value, - }, - }, + totalCompensation: exp.totalCompensation + ? { + create: { + baseCurrency: baseCurrencyString, + baseValue: await convert( + exp.totalCompensation.value, + exp.totalCompensation.currency, + baseCurrencyString, + ), + currency: exp.totalCompensation.currency, + value: exp.totalCompensation.value, + }, + } + : undefined, }, }, }, diff --git a/apps/portal/src/utils/offers/form.tsx b/apps/portal/src/utils/offers/form.tsx index 2e88ac88..ac03e281 100644 --- a/apps/portal/src/utils/offers/form.tsx +++ b/apps/portal/src/utils/offers/form.tsx @@ -32,6 +32,33 @@ export function cleanObject(object: any) { return object; } +/** + * Removes empty objects from an object. + * @param object + * @returns object without empty values or objects. + */ +export function removeEmptyObjects(object: any) { + Object.entries(object).forEach(([k, v]) => { + if ((v && typeof v === 'object') || Array.isArray(v)) { + removeEmptyObjects(v); + } + if ( + v && + typeof v === 'object' && + !Object.keys(v).length && + !Array.isArray(v) + ) { + if (Array.isArray(object)) { + const index = object.indexOf(v); + object.splice(index, 1); + } else if (!(v instanceof Date)) { + delete object[k]; + } + } + }); + return object; +} + /** * Removes invalid money data from an object. * If currency is present but value is not present, money object is removed.