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.