mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2026-02-03 02:24:47 +08:00
[offers][feat] Tweak UI and add View More button to OEA (#507)
* [offers][feat] Tweak UI and minor refactoring * [offers][feat] Add view more button to OEA
This commit is contained in:
@@ -63,7 +63,7 @@ export default function DashboardProfileCard({
|
||||
{profileName}
|
||||
</h2>
|
||||
<p className="text-sm text-slate-500">
|
||||
<span>Created at {formatDate(createdAt)}</span>
|
||||
<span>Created in {formatDate(createdAt)}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Alert, HorizontalDivider, Spinner, Tabs } from '@tih/ui';
|
||||
import { ArrowUpRightIcon } from '@heroicons/react/24/outline';
|
||||
import { JobType } from '@prisma/client';
|
||||
import { Alert, Button, HorizontalDivider, Spinner, Tabs } from '@tih/ui';
|
||||
|
||||
import OfferPercentileAnalysisText from './OfferPercentileAnalysisText';
|
||||
import OfferProfileCard from './OfferProfileCard';
|
||||
import { OVERALL_TAB } from '../constants';
|
||||
import { YOE_CATEGORY } from '../table/types';
|
||||
|
||||
import type { AnalysisUnit, ProfileAnalysis } from '~/types/offers';
|
||||
|
||||
@@ -19,6 +22,16 @@ function OfferAnalysisContent({
|
||||
tab,
|
||||
isSubmission,
|
||||
}: OfferAnalysisContentProps) {
|
||||
const { companyId, companyName, title, totalYoe, jobType } = analysis;
|
||||
const yoeCategory =
|
||||
jobType === JobType.INTERN
|
||||
? ''
|
||||
: totalYoe <= 2
|
||||
? YOE_CATEGORY.ENTRY
|
||||
: totalYoe <= 5
|
||||
? YOE_CATEGORY.MID
|
||||
: YOE_CATEGORY.SENIOR;
|
||||
|
||||
if (!analysis || analysis.noOfOffers === 0) {
|
||||
if (tab === OVERALL_TAB) {
|
||||
return (
|
||||
@@ -55,15 +68,22 @@ function OfferAnalysisContent({
|
||||
offerProfile={topPercentileOffer}
|
||||
/>
|
||||
))}
|
||||
{/* {offerAnalysis.topPercentileOffers.length > 0 && (
|
||||
{analysis.topPercentileOffers.length > 0 && (
|
||||
<div className="mb-4 flex justify-end">
|
||||
<Button
|
||||
icon={EllipsisHorizontalIcon}
|
||||
href={
|
||||
tab === OVERALL_TAB
|
||||
? `/offers?jobTitleId=${title}&sortBy=-totalCompensation&yoeCategory=${yoeCategory}`
|
||||
: `/offers?companyId=${companyId}&companyName=${companyName}&jobTitleId=${title}&sortBy=-totalCompensation&yoeCategory=${yoeCategory}`
|
||||
}
|
||||
icon={ArrowUpRightIcon}
|
||||
label="View more offers"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
variant="tertiary"
|
||||
/>
|
||||
</div>
|
||||
)} */}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -133,4 +153,4 @@ export default function OfferAnalysis({
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import {
|
||||
ArrowTrendingUpIcon,
|
||||
BuildingOfficeIcon,
|
||||
MapPinIcon,
|
||||
} from '@heroicons/react/20/solid';
|
||||
import {
|
||||
ArrowTopRightOnSquareIcon,
|
||||
BuildingOffice2Icon,
|
||||
CalendarDaysIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
@@ -7,9 +13,8 @@ import { JobType } from '@prisma/client';
|
||||
import type { JobTitleType } from '~/components/shared/JobTitles';
|
||||
import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
|
||||
|
||||
import { HorizontalDivider } from '~/../../../packages/ui/dist';
|
||||
import { Button } from '~/../../../packages/ui/dist';
|
||||
import { convertMoneyToString } from '~/utils/offers/currency';
|
||||
import { getCompanyDisplayText } from '~/utils/offers/string';
|
||||
import { formatDate } from '~/utils/offers/time';
|
||||
|
||||
import { JobTypeLabel } from '../constants';
|
||||
@@ -36,52 +41,109 @@ export default function OfferProfileCard({
|
||||
profileId,
|
||||
},
|
||||
}: OfferProfileCardProps) {
|
||||
return (
|
||||
<a
|
||||
className="my-5 block rounded-lg border bg-white p-4 px-8 shadow-md"
|
||||
href={`/offers/profile/${profileId}`}
|
||||
rel="noreferrer"
|
||||
target="_blank">
|
||||
<div className="flex items-center gap-x-5">
|
||||
<div>
|
||||
<ProfilePhotoHolder size="sm" />
|
||||
</div>
|
||||
<div className="col-span-10">
|
||||
<p className="font-bold">{profileName}</p>
|
||||
{previousCompanies.length > 0 && (
|
||||
<div className="flex flex-row">
|
||||
<BuildingOffice2Icon className="mr-2 h-5" />
|
||||
<span className="mr-2 font-bold">Current:</span>
|
||||
<span>{previousCompanies[0]}</span>
|
||||
function UpperSection() {
|
||||
return (
|
||||
<div className="border-b px-4 py-5 sm:px-6">
|
||||
<div className="-ml-4 -mt-4 flex flex-wrap items-center justify-between sm:flex-nowrap">
|
||||
<div className="ml-4 mt-4">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<ProfilePhotoHolder size="sm" />
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<h2 className="text-lg font-medium leading-6 text-slate-900">
|
||||
{profileName}
|
||||
</h2>
|
||||
<p className="flex text-sm text-slate-500">
|
||||
<CalendarDaysIcon className="mr-2 h-5" />
|
||||
<span className="mr-2 font-bold">YOE:</span>
|
||||
<span>{totalYoe}</span>
|
||||
{previousCompanies.length > 0 && (
|
||||
<>
|
||||
<BuildingOffice2Icon className="ml-4 mr-2 h-5" />
|
||||
<span className="mr-2 font-bold">Previous:</span>
|
||||
<span>{previousCompanies[0]}</span>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-row">
|
||||
<CalendarDaysIcon className="mr-2 h-5" />
|
||||
<span className="mr-2 font-bold">YOE:</span>
|
||||
<span>{totalYoe}</span>
|
||||
</div>
|
||||
<div className="ml-4 mt-4 flex flex-shrink-0">
|
||||
<Button
|
||||
href={`/offers/profile/${profileId}`}
|
||||
icon={ArrowTopRightOnSquareIcon}
|
||||
isLabelHidden={true}
|
||||
label="View Profile"
|
||||
rel="noreferrer"
|
||||
size="md"
|
||||
target="_blank"
|
||||
variant="tertiary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<HorizontalDivider />
|
||||
<div className="flex items-end justify-between">
|
||||
<div className="col-span-1 row-span-3">
|
||||
<p className="font-bold">
|
||||
{getLabelForJobTitleType(title as JobTitleType)}{' '}
|
||||
{`(${JobTypeLabel[jobType]})`}
|
||||
</p>
|
||||
<p>{`Company: ${getCompanyDisplayText(company.name, location)}`}</p>
|
||||
{level && <p>Level: {level}</p>}
|
||||
</div>
|
||||
<div className="col-span-1 row-span-3">
|
||||
<p className="text-end">{formatDate(monthYearReceived)}</p>
|
||||
<p className="text-end text-xl">
|
||||
{jobType === JobType.FULLTIME
|
||||
? `${convertMoneyToString(income)} / year`
|
||||
: `${convertMoneyToString(income)} / month`}
|
||||
</p>
|
||||
function BottomSection() {
|
||||
return (
|
||||
<div className="px-4 py-4 sm:px-6">
|
||||
<div className="flex items-end justify-between">
|
||||
<div className="col-span-1 row-span-3">
|
||||
<h4 className="font-medium">
|
||||
{getLabelForJobTitleType(title as JobTitleType)}{' '}
|
||||
{jobType && <>({JobTypeLabel[jobType]})</>}
|
||||
</h4>
|
||||
<div className="mt-1 flex flex-col sm:mt-0 sm:flex-row sm:flex-wrap sm:space-x-4">
|
||||
{company?.name && (
|
||||
<div className="mt-2 flex items-center text-sm text-slate-500">
|
||||
<BuildingOfficeIcon
|
||||
aria-hidden="true"
|
||||
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
|
||||
/>
|
||||
{company.name}
|
||||
</div>
|
||||
)}
|
||||
{location && (
|
||||
<div className="mt-2 flex items-center text-sm text-slate-500">
|
||||
<MapPinIcon
|
||||
aria-hidden="true"
|
||||
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
|
||||
/>
|
||||
{location.cityName}
|
||||
</div>
|
||||
)}
|
||||
{level && (
|
||||
<div className="mt-2 flex items-center text-sm text-slate-500">
|
||||
<ArrowTrendingUpIcon
|
||||
aria-hidden="true"
|
||||
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
|
||||
/>
|
||||
{level}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-1 row-span-3">
|
||||
<p className="text-end text-lg font-medium leading-6 text-slate-900">
|
||||
{jobType === JobType.FULLTIME
|
||||
? `${convertMoneyToString(income)} / year`
|
||||
: `${convertMoneyToString(income)} / month`}
|
||||
</p>
|
||||
<p className="text-end text-sm text-slate-500">
|
||||
{formatDate(monthYearReceived)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="my-5 block rounded-lg border border-slate-200 bg-white">
|
||||
<UpperSection />
|
||||
<BottomSection />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,12 @@ import BackgroundForm from '~/components/offers/offersSubmission/submissionForm/
|
||||
import OfferDetailsForm from '~/components/offers/offersSubmission/submissionForm/OfferDetailsForm';
|
||||
import type {
|
||||
OfferFormData,
|
||||
OfferPostData,
|
||||
OffersProfileFormData,
|
||||
} from '~/components/offers/types';
|
||||
import type { Month } from '~/components/shared/MonthYearPicker';
|
||||
|
||||
import { Currency } from '~/utils/offers/currency/CurrencyEnum';
|
||||
import {
|
||||
cleanObject,
|
||||
removeEmptyObjects,
|
||||
@@ -25,6 +27,8 @@ import {
|
||||
import { getCurrentMonth, getCurrentYear } from '~/utils/offers/time';
|
||||
import { trpc } from '~/utils/trpc';
|
||||
|
||||
export const DEFAULT_CURRENCY = Currency.SGD;
|
||||
|
||||
const defaultOfferValues = {
|
||||
cityId: '',
|
||||
comments: '',
|
||||
@@ -43,21 +47,17 @@ export const defaultFullTimeOfferValues = {
|
||||
jobType: JobType.FULLTIME,
|
||||
offersFullTime: {
|
||||
baseSalary: {
|
||||
currency: 'SGD',
|
||||
value: null,
|
||||
currency: DEFAULT_CURRENCY,
|
||||
},
|
||||
bonus: {
|
||||
currency: 'SGD',
|
||||
value: null,
|
||||
currency: DEFAULT_CURRENCY,
|
||||
},
|
||||
level: '',
|
||||
stocks: {
|
||||
currency: 'SGD',
|
||||
value: null,
|
||||
currency: DEFAULT_CURRENCY,
|
||||
},
|
||||
totalCompensation: {
|
||||
currency: 'SGD',
|
||||
value: null,
|
||||
currency: DEFAULT_CURRENCY,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -66,16 +66,15 @@ export const defaultInternshipOfferValues = {
|
||||
...defaultOfferValues,
|
||||
jobType: JobType.INTERN,
|
||||
offersIntern: {
|
||||
internshipCycle: null,
|
||||
internshipCycle: '',
|
||||
monthlySalary: {
|
||||
currency: 'SGD',
|
||||
value: null,
|
||||
currency: DEFAULT_CURRENCY,
|
||||
},
|
||||
startYear: null,
|
||||
},
|
||||
};
|
||||
|
||||
const defaultOfferProfileValues = {
|
||||
const defaultOfferProfileValues: OffersProfileFormData = {
|
||||
background: {
|
||||
educations: [],
|
||||
experiences: [{ jobType: JobType.FULLTIME }],
|
||||
@@ -116,7 +115,7 @@ export default function OffersSubmissionForm({
|
||||
const {
|
||||
handleSubmit,
|
||||
trigger,
|
||||
formState: { isSubmitting },
|
||||
formState: { isSubmitting, isDirty },
|
||||
} = formMethods;
|
||||
|
||||
const generateAnalysisMutation = trpc.useMutation(
|
||||
@@ -218,7 +217,7 @@ export default function OffersSubmissionForm({
|
||||
offer.monthYearReceived.year,
|
||||
offer.monthYearReceived.month - 1, // Convert month to monthIndex
|
||||
),
|
||||
}));
|
||||
})) as Array<OfferPostData>;
|
||||
|
||||
if (params.profileId && params.token) {
|
||||
createOrUpdateMutation.mutate({
|
||||
@@ -254,11 +253,14 @@ export default function OffersSubmissionForm({
|
||||
const warningText =
|
||||
'Leave this page? Changes that you made will not be saved.';
|
||||
const handleWindowClose = (e: BeforeUnloadEvent) => {
|
||||
if (!isDirty) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
return (e.returnValue = warningText);
|
||||
};
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('/offers/submit/result')) {
|
||||
if (url.includes('/offers/submit/result') || !isDirty) {
|
||||
return;
|
||||
}
|
||||
if (window.confirm(warningText)) {
|
||||
@@ -274,7 +276,7 @@ export default function OffersSubmissionForm({
|
||||
router.events.off('routeChangeStart', handleRouteChange);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [isDirty]);
|
||||
|
||||
return generateAnalysisMutation.isLoading ? (
|
||||
<Spinner className="m-10" display="block" size="lg" />
|
||||
@@ -353,4 +355,4 @@ export default function OffersSubmissionForm({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ function FullTimeOfferDetailsForm({
|
||||
onSelect={(option) => {
|
||||
if (option) {
|
||||
setValue(`offers.${index}.companyId`, option.value);
|
||||
setValue(`offers.${index}.companyName`, option.label);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -550,7 +551,6 @@ export default function OfferDetailsForm() {
|
||||
if (newJobType === jobType) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDialogOpen(true);
|
||||
}}
|
||||
/>
|
||||
@@ -586,4 +586,4 @@ export default function OfferDetailsForm() {
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,9 +131,8 @@ function ProfileAnalysis({
|
||||
{isEditable && (
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
addonPosition="start"
|
||||
icon={ArrowPathIcon}
|
||||
label="Regenerate Analysis"
|
||||
label="Regenerate analysis"
|
||||
variant="secondary"
|
||||
onClick={() => generateAnalysisMutation.mutate({ profileId })}
|
||||
/>
|
||||
@@ -188,4 +187,4 @@ export default function ProfileDetails({
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,101 @@ import type { MonthYear } from '~/components/shared/MonthYearPicker';
|
||||
|
||||
import type { Location } from '~/types/offers';
|
||||
|
||||
/**
|
||||
* Form data types
|
||||
*/
|
||||
|
||||
export type OffersProfileFormData = {
|
||||
background: BackgroundFormData;
|
||||
id?: string;
|
||||
offers: Array<OfferFormData>;
|
||||
};
|
||||
|
||||
export type BackgroundFormData = {
|
||||
educations: Array<EducationFormData>;
|
||||
experiences: Array<ExperienceFormData>;
|
||||
id?: string;
|
||||
specificYoes: Array<SpecificYoeFormData>;
|
||||
totalYoe: number;
|
||||
};
|
||||
|
||||
type EducationFormData = {
|
||||
endDate?: Date | null;
|
||||
field?: string | null;
|
||||
school?: string | null;
|
||||
startDate?: Date | null;
|
||||
type?: string | null;
|
||||
};
|
||||
|
||||
type ExperienceFormData = {
|
||||
cityId?: string | null;
|
||||
cityName?: string | null;
|
||||
companyId?: string | null;
|
||||
companyName?: string | null;
|
||||
durationInMonths?: number | null;
|
||||
id?: string;
|
||||
jobType?: string | null;
|
||||
level?: string | null;
|
||||
monthlySalary?: MoneyFormData | null;
|
||||
title?: string | null;
|
||||
totalCompensation?: MoneyFormData | null;
|
||||
totalCompensationId?: string | null;
|
||||
};
|
||||
|
||||
type SpecificYoeFormData = {
|
||||
domain: string;
|
||||
id?: string;
|
||||
yoe: number;
|
||||
};
|
||||
|
||||
export type OfferFormData = {
|
||||
cityId: string;
|
||||
cityName?: string;
|
||||
comments: string;
|
||||
companyId: string;
|
||||
companyName?: string;
|
||||
id?: string;
|
||||
jobType: JobType;
|
||||
monthYearReceived: MonthYear;
|
||||
negotiationStrategy: string;
|
||||
offersFullTime?: OfferFullTimeFormData | null;
|
||||
offersIntern?: OfferInternFormData | null;
|
||||
};
|
||||
|
||||
export type OfferFullTimeFormData = {
|
||||
baseSalary?: MoneyFormData | null;
|
||||
bonus?: MoneyFormData | null;
|
||||
id?: string;
|
||||
level: string;
|
||||
stocks?: MoneyFormData | null;
|
||||
title: string;
|
||||
totalCompensation: MoneyFormData;
|
||||
};
|
||||
|
||||
export type OfferInternFormData = {
|
||||
id?: string;
|
||||
internshipCycle: string;
|
||||
monthlySalary: MoneyFormData;
|
||||
startYear: number;
|
||||
title: string;
|
||||
};
|
||||
|
||||
type MoneyFormData = {
|
||||
currency: string;
|
||||
id?: string;
|
||||
value?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Post request data types
|
||||
*/
|
||||
|
||||
export type OffersProfilePostData = {
|
||||
background: BackgroundPostData;
|
||||
id?: string;
|
||||
offers: Array<OfferPostData>;
|
||||
};
|
||||
|
||||
export type OffersProfileFormData = {
|
||||
background: BackgroundPostData;
|
||||
id?: string;
|
||||
offers: Array<OfferFormData>;
|
||||
};
|
||||
|
||||
export type BackgroundPostData = {
|
||||
educations: Array<EducationPostData>;
|
||||
experiences: Array<ExperiencePostData>;
|
||||
@@ -24,6 +107,8 @@ export type BackgroundPostData = {
|
||||
totalYoe: number;
|
||||
};
|
||||
|
||||
type EducationPostData = EducationFormData;
|
||||
|
||||
type ExperiencePostData = {
|
||||
cityId?: string | null;
|
||||
cityName?: string | null;
|
||||
@@ -39,47 +124,26 @@ type ExperiencePostData = {
|
||||
totalCompensationId?: string | null;
|
||||
};
|
||||
|
||||
type EducationPostData = {
|
||||
endDate?: Date | null;
|
||||
field?: string | null;
|
||||
id?: string;
|
||||
school?: string | null;
|
||||
startDate?: Date | null;
|
||||
type?: string | null;
|
||||
};
|
||||
|
||||
type SpecificYoePostData = {
|
||||
domain: string;
|
||||
id?: string;
|
||||
yoe: number;
|
||||
};
|
||||
|
||||
type SpecificYoe = SpecificYoePostData;
|
||||
type SpecificYoePostData = SpecificYoeFormData;
|
||||
|
||||
export type OfferPostData = {
|
||||
cityId: string;
|
||||
cityName?: string;
|
||||
comments: string;
|
||||
companyId: string;
|
||||
companyName?: string;
|
||||
id?: string;
|
||||
jobType: JobType;
|
||||
monthYearReceived: Date;
|
||||
negotiationStrategy: string;
|
||||
offersFullTime?: OfferFullTimePostData | null;
|
||||
offersIntern?: OfferInternPostData | null;
|
||||
};
|
||||
|
||||
export type OfferFormData = Omit<OfferPostData, 'monthYearReceived'> & {
|
||||
monthYearReceived: MonthYear;
|
||||
offersFullTime?: OfferFullTimePostData;
|
||||
offersIntern?: OfferInternPostData;
|
||||
};
|
||||
|
||||
export type OfferFullTimePostData = {
|
||||
baseSalary: Money | null;
|
||||
bonus: Money | null;
|
||||
baseSalary: Money;
|
||||
bonus: Money;
|
||||
id?: string;
|
||||
level: string;
|
||||
stocks: Money | null;
|
||||
stocks: Money;
|
||||
title: string;
|
||||
totalCompensation: Money;
|
||||
};
|
||||
@@ -98,6 +162,10 @@ export type Money = {
|
||||
value: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Display data types
|
||||
*/
|
||||
|
||||
export type EducationDisplayData = {
|
||||
endDate?: string | null;
|
||||
field?: string | null;
|
||||
@@ -128,7 +196,7 @@ export type BackgroundDisplayData = {
|
||||
educations: Array<EducationDisplayData>;
|
||||
experiences: Array<OfferDisplayData>;
|
||||
profileName: string;
|
||||
specificYoes: Array<SpecificYoe>;
|
||||
specificYoes: Array<SpecificYoePostData>;
|
||||
totalYoe: number;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
import { JobType } from '@prisma/client';
|
||||
|
||||
import OffersSubmissionForm from '~/components/offers/offersSubmission/OffersSubmissionForm';
|
||||
import OffersSubmissionForm, {
|
||||
DEFAULT_CURRENCY,
|
||||
} from '~/components/offers/offersSubmission/OffersSubmissionForm';
|
||||
import type { OffersProfileFormData } from '~/components/offers/types';
|
||||
|
||||
import { Spinner } from '~/../../../packages/ui/dist';
|
||||
@@ -44,9 +46,16 @@ export default function OffersEditPage() {
|
||||
id: exp.id,
|
||||
jobType: exp.jobType,
|
||||
level: exp.level,
|
||||
monthlySalary: exp.monthlySalary,
|
||||
monthlySalary: {
|
||||
currency: exp.monthlySalary?.currency || DEFAULT_CURRENCY,
|
||||
value: exp.monthlySalary?.value,
|
||||
},
|
||||
title: exp.title,
|
||||
totalCompensation: exp.totalCompensation,
|
||||
totalCompensation: {
|
||||
currency:
|
||||
exp.totalCompensation?.currency || DEFAULT_CURRENCY,
|
||||
value: exp.totalCompensation?.value,
|
||||
},
|
||||
})),
|
||||
id,
|
||||
specificYoes,
|
||||
|
||||
Reference in New Issue
Block a user