|
|
@ -10,7 +10,7 @@ import { useFieldArray } from 'react-hook-form';
|
|
|
|
import { PlusIcon } from '@heroicons/react/20/solid';
|
|
|
|
import { PlusIcon } from '@heroicons/react/20/solid';
|
|
|
|
import { TrashIcon } from '@heroicons/react/24/outline';
|
|
|
|
import { TrashIcon } from '@heroicons/react/24/outline';
|
|
|
|
import { JobType } from '@prisma/client';
|
|
|
|
import { JobType } from '@prisma/client';
|
|
|
|
import { Button, Dialog } from '@tih/ui';
|
|
|
|
import { Button, Dialog, HorizontalDivider } from '@tih/ui';
|
|
|
|
|
|
|
|
|
|
|
|
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
|
|
|
|
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
|
|
|
|
import type { JobTitleType } from '~/components/shared/JobTitles';
|
|
|
|
import type { JobTitleType } from '~/components/shared/JobTitles';
|
|
|
@ -45,6 +45,23 @@ type FullTimeOfferDetailsFormProps = Readonly<{
|
|
|
|
remove: UseFieldArrayRemove;
|
|
|
|
remove: UseFieldArrayRemove;
|
|
|
|
}>;
|
|
|
|
}>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function Section({
|
|
|
|
|
|
|
|
children,
|
|
|
|
|
|
|
|
title,
|
|
|
|
|
|
|
|
}: Readonly<{ children: React.ReactNode; title: string }>) {
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<div className="mb-4">
|
|
|
|
|
|
|
|
<h3 className="text-lg font-medium leading-6 text-slate-900">
|
|
|
|
|
|
|
|
{title}
|
|
|
|
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<HorizontalDivider />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="space-y-4 sm:space-y-6">{children}</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function FullTimeOfferDetailsForm({
|
|
|
|
function FullTimeOfferDetailsForm({
|
|
|
|
index,
|
|
|
|
index,
|
|
|
|
remove,
|
|
|
|
remove,
|
|
|
@ -77,9 +94,9 @@ function FullTimeOfferDetailsForm({
|
|
|
|
}, [watchCurrency, index, setValue]);
|
|
|
|
}, [watchCurrency, index, setValue]);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className="my-5 rounded-lg border border-slate-200 px-10 py-5">
|
|
|
|
<div className="space-y-8 rounded-lg border border-slate-200 p-6 sm:space-y-16 sm:p-8">
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
<Section title="Company & Title Information">
|
|
|
|
<div>
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
|
|
|
<JobTitlesTypeahead
|
|
|
|
<JobTitlesTypeahead
|
|
|
|
required={true}
|
|
|
|
required={true}
|
|
|
|
value={{
|
|
|
|
value={{
|
|
|
@ -93,19 +110,17 @@ function FullTimeOfferDetailsForm({
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
<FormTextInput
|
|
|
|
|
|
|
|
errorMessage={offerFields?.offersFullTime?.level?.message}
|
|
|
|
|
|
|
|
label="Level"
|
|
|
|
|
|
|
|
placeholder="e.g. L4, Junior"
|
|
|
|
|
|
|
|
required={true}
|
|
|
|
|
|
|
|
{...register(`offers.${index}.offersFullTime.level`, {
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<FormTextInput
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
|
|
|
errorMessage={offerFields?.offersFullTime?.level?.message}
|
|
|
|
|
|
|
|
label="Level"
|
|
|
|
|
|
|
|
placeholder="e.g. L4, Junior"
|
|
|
|
|
|
|
|
required={true}
|
|
|
|
|
|
|
|
{...register(`offers.${index}.offersFullTime.level`, {
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<CompaniesTypeahead
|
|
|
|
<CompaniesTypeahead
|
|
|
|
required={true}
|
|
|
|
required={true}
|
|
|
|
value={{
|
|
|
|
value={{
|
|
|
@ -120,165 +135,168 @@ function FullTimeOfferDetailsForm({
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
<FormSelect
|
|
|
|
|
|
|
|
display="block"
|
|
|
|
|
|
|
|
errorMessage={offerFields?.location?.message}
|
|
|
|
|
|
|
|
label="Location"
|
|
|
|
|
|
|
|
options={locationOptions}
|
|
|
|
|
|
|
|
placeholder={emptyOption}
|
|
|
|
|
|
|
|
required={true}
|
|
|
|
|
|
|
|
{...register(`offers.${index}.location`, {
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<FormSelect
|
|
|
|
</Section>
|
|
|
|
display="block"
|
|
|
|
<Section title="Compensation Details">
|
|
|
|
errorMessage={offerFields?.location?.message}
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
|
|
|
label="Location"
|
|
|
|
<FormMonthYearPicker
|
|
|
|
options={locationOptions}
|
|
|
|
monthLabel="Date Received"
|
|
|
|
placeholder={emptyOption}
|
|
|
|
monthRequired={true}
|
|
|
|
required={true}
|
|
|
|
yearLabel=""
|
|
|
|
{...register(`offers.${index}.location`, {
|
|
|
|
{...register(`offers.${index}.monthYearReceived`, {
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5 flex grid grid-cols-2 items-start space-x-3">
|
|
|
|
|
|
|
|
<FormMonthYearPicker
|
|
|
|
|
|
|
|
monthLabel="Date Received"
|
|
|
|
|
|
|
|
monthRequired={true}
|
|
|
|
|
|
|
|
yearLabel=""
|
|
|
|
|
|
|
|
{...register(`offers.${index}.monthYearReceived`, {
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5">
|
|
|
|
|
|
|
|
<FormTextInput
|
|
|
|
|
|
|
|
endAddOn={
|
|
|
|
|
|
|
|
<FormSelect
|
|
|
|
|
|
|
|
borderStyle="borderless"
|
|
|
|
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
|
|
|
|
isLabelHidden={true}
|
|
|
|
|
|
|
|
label="Currency"
|
|
|
|
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
|
|
|
|
{...register(
|
|
|
|
|
|
|
|
`offers.${index}.offersFullTime.totalCompensation.currency`,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<FormTextInput
|
|
|
|
|
|
|
|
endAddOn={
|
|
|
|
|
|
|
|
<FormSelect
|
|
|
|
|
|
|
|
borderStyle="borderless"
|
|
|
|
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
|
|
|
|
isLabelHidden={true}
|
|
|
|
|
|
|
|
label="Currency"
|
|
|
|
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
|
|
|
|
{...register(
|
|
|
|
|
|
|
|
`offers.${index}.offersFullTime.totalCompensation.currency`,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-3">
|
|
|
|
|
|
|
|
<FormTextInput
|
|
|
|
|
|
|
|
endAddOn={
|
|
|
|
|
|
|
|
<FormSelect
|
|
|
|
|
|
|
|
borderStyle="borderless"
|
|
|
|
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
|
|
|
|
isLabelHidden={true}
|
|
|
|
|
|
|
|
label="Currency"
|
|
|
|
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
|
|
|
|
{...register(
|
|
|
|
|
|
|
|
`offers.${index}.offersFullTime.baseSalary.currency`,
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
valueAsNumber: true,
|
|
|
|
},
|
|
|
|
})}
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
<FormTextInput
|
|
|
|
</div>
|
|
|
|
endAddOn={
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
<FormSelect
|
|
|
|
<FormTextInput
|
|
|
|
borderStyle="borderless"
|
|
|
|
endAddOn={
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
<FormSelect
|
|
|
|
isLabelHidden={true}
|
|
|
|
borderStyle="borderless"
|
|
|
|
label="Currency"
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
isLabelHidden={true}
|
|
|
|
{...register(`offers.${index}.offersFullTime.bonus.currency`)}
|
|
|
|
label="Currency"
|
|
|
|
/>
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
}
|
|
|
|
{...register(
|
|
|
|
endAddOnType="element"
|
|
|
|
`offers.${index}.offersFullTime.baseSalary.currency`,
|
|
|
|
errorMessage={offerFields?.offersFullTime?.bonus?.value?.message}
|
|
|
|
)}
|
|
|
|
label="Bonus (Annual)"
|
|
|
|
/>
|
|
|
|
placeholder="0"
|
|
|
|
}
|
|
|
|
startAddOn="$"
|
|
|
|
endAddOnType="element"
|
|
|
|
startAddOnType="label"
|
|
|
|
errorMessage={offerFields?.offersFullTime?.baseSalary?.value?.message}
|
|
|
|
type="number"
|
|
|
|
label="Base Salary (Annual)"
|
|
|
|
{...register(`offers.${index}.offersFullTime.bonus.value`, {
|
|
|
|
placeholder="0"
|
|
|
|
min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 },
|
|
|
|
startAddOn="$"
|
|
|
|
valueAsNumber: true,
|
|
|
|
startAddOnType="label"
|
|
|
|
})}
|
|
|
|
type="number"
|
|
|
|
/>
|
|
|
|
{...register(`offers.${index}.offersFullTime.baseSalary.value`, {
|
|
|
|
<FormTextInput
|
|
|
|
min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 },
|
|
|
|
endAddOn={
|
|
|
|
valueAsNumber: true,
|
|
|
|
<FormSelect
|
|
|
|
})}
|
|
|
|
borderStyle="borderless"
|
|
|
|
/>
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
<FormTextInput
|
|
|
|
isLabelHidden={true}
|
|
|
|
endAddOn={
|
|
|
|
label="Currency"
|
|
|
|
<FormSelect
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
borderStyle="borderless"
|
|
|
|
{...register(`offers.${index}.offersFullTime.stocks.currency`)}
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
/>
|
|
|
|
isLabelHidden={true}
|
|
|
|
}
|
|
|
|
label="Currency"
|
|
|
|
endAddOnType="element"
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
errorMessage={offerFields?.offersFullTime?.stocks?.value?.message}
|
|
|
|
{...register(`offers.${index}.offersFullTime.bonus.currency`)}
|
|
|
|
label="Stocks (Annual)"
|
|
|
|
/>
|
|
|
|
placeholder="0"
|
|
|
|
}
|
|
|
|
startAddOn="$"
|
|
|
|
endAddOnType="element"
|
|
|
|
startAddOnType="label"
|
|
|
|
errorMessage={offerFields?.offersFullTime?.bonus?.value?.message}
|
|
|
|
type="number"
|
|
|
|
label="Bonus (Annual)"
|
|
|
|
{...register(`offers.${index}.offersFullTime.stocks.value`, {
|
|
|
|
placeholder="0"
|
|
|
|
min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 },
|
|
|
|
startAddOn="$"
|
|
|
|
valueAsNumber: true,
|
|
|
|
startAddOnType="label"
|
|
|
|
})}
|
|
|
|
type="number"
|
|
|
|
/>
|
|
|
|
{...register(`offers.${index}.offersFullTime.bonus.value`, {
|
|
|
|
</div>
|
|
|
|
min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 },
|
|
|
|
</Section>
|
|
|
|
valueAsNumber: true,
|
|
|
|
<Section title="Additional Information">
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
|
|
|
|
<FormTextInput
|
|
|
|
|
|
|
|
endAddOn={
|
|
|
|
|
|
|
|
<FormSelect
|
|
|
|
|
|
|
|
borderStyle="borderless"
|
|
|
|
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
|
|
|
|
isLabelHidden={true}
|
|
|
|
|
|
|
|
label="Currency"
|
|
|
|
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
|
|
|
|
{...register(`offers.${index}.offersFullTime.stocks.currency`)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5">
|
|
|
|
|
|
|
|
<FormTextArea
|
|
|
|
<FormTextArea
|
|
|
|
label="Negotiation Strategy / Interview Performance"
|
|
|
|
label="Negotiation Strategy / Interview Performance"
|
|
|
|
placeholder="e.g. Did well in the behavioral interview / Used competing offers to negotiate for a higher salary"
|
|
|
|
placeholder="e.g. Did well in the behavioral interview / Used competing offers to negotiate for a higher salary"
|
|
|
|
{...register(`offers.${index}.negotiationStrategy`)}
|
|
|
|
{...register(`offers.${index}.negotiationStrategy`)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5">
|
|
|
|
|
|
|
|
<FormTextArea
|
|
|
|
<FormTextArea
|
|
|
|
label="Comments"
|
|
|
|
label="Comments"
|
|
|
|
placeholder="e.g. Benefits offered by the company"
|
|
|
|
placeholder="e.g. Benefits offered by the company"
|
|
|
|
{...register(`offers.${index}.comments`)}
|
|
|
|
{...register(`offers.${index}.comments`)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="flex justify-end">
|
|
|
|
|
|
|
|
{index > 0 && (
|
|
|
|
{index > 0 && (
|
|
|
|
<Button
|
|
|
|
<div className="space-y-4 sm:space-y-6">
|
|
|
|
icon={TrashIcon}
|
|
|
|
<HorizontalDivider />
|
|
|
|
label="Delete"
|
|
|
|
<div className="flex justify-end">
|
|
|
|
variant="secondary"
|
|
|
|
<Button
|
|
|
|
onClick={() => remove(index)}
|
|
|
|
icon={TrashIcon}
|
|
|
|
/>
|
|
|
|
label="Delete"
|
|
|
|
|
|
|
|
variant="tertiary"
|
|
|
|
|
|
|
|
onClick={() => {
|
|
|
|
|
|
|
|
remove(index);
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</Section>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -308,26 +326,23 @@ function InternshipOfferDetailsForm({
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className="my-5 rounded-lg border border-slate-200 px-10 py-5">
|
|
|
|
<div className="space-y-8 rounded-lg border border-slate-200 p-6 sm:space-y-16 sm:p-8">
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
<Section title="Company & Title Information">
|
|
|
|
<div>
|
|
|
|
<JobTitlesTypeahead
|
|
|
|
<JobTitlesTypeahead
|
|
|
|
required={true}
|
|
|
|
required={true}
|
|
|
|
value={{
|
|
|
|
value={{
|
|
|
|
id: watchJobTitle,
|
|
|
|
id: watchJobTitle,
|
|
|
|
label: getLabelForJobTitleType(watchJobTitle as JobTitleType),
|
|
|
|
label: getLabelForJobTitleType(watchJobTitle as JobTitleType),
|
|
|
|
value: watchJobTitle,
|
|
|
|
value: watchJobTitle,
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
onSelect={(option) => {
|
|
|
|
onSelect={(option) => {
|
|
|
|
if (option) {
|
|
|
|
if (option) {
|
|
|
|
setValue(`offers.${index}.offersIntern.title`, option.value);
|
|
|
|
setValue(`offers.${index}.offersIntern.title`, option.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<CompaniesTypeahead
|
|
|
|
<CompaniesTypeahead
|
|
|
|
required={true}
|
|
|
|
required={true}
|
|
|
|
value={{
|
|
|
|
value={{
|
|
|
@ -342,114 +357,115 @@ function InternshipOfferDetailsForm({
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
<FormSelect
|
|
|
|
|
|
|
|
display="block"
|
|
|
|
|
|
|
|
errorMessage={offerFields?.location?.message}
|
|
|
|
|
|
|
|
label="Location"
|
|
|
|
|
|
|
|
options={locationOptions}
|
|
|
|
|
|
|
|
placeholder={emptyOption}
|
|
|
|
|
|
|
|
required={true}
|
|
|
|
|
|
|
|
{...register(`offers.${index}.location`, {
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<FormSelect
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
|
|
|
display="block"
|
|
|
|
<FormSelect
|
|
|
|
errorMessage={offerFields?.location?.message}
|
|
|
|
display="block"
|
|
|
|
label="Location"
|
|
|
|
errorMessage={offerFields?.offersIntern?.internshipCycle?.message}
|
|
|
|
options={locationOptions}
|
|
|
|
label="Internship Cycle"
|
|
|
|
placeholder={emptyOption}
|
|
|
|
options={internshipCycleOptions}
|
|
|
|
required={true}
|
|
|
|
placeholder={emptyOption}
|
|
|
|
{...register(`offers.${index}.location`, {
|
|
|
|
required={true}
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
{...register(`offers.${index}.offersIntern.internshipCycle`, {
|
|
|
|
})}
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
/>
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
/>
|
|
|
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
|
|
|
<FormSelect
|
|
|
|
<FormSelect
|
|
|
|
display="block"
|
|
|
|
display="block"
|
|
|
|
errorMessage={offerFields?.offersIntern?.startYear?.message}
|
|
|
|
errorMessage={offerFields?.offersIntern?.internshipCycle?.message}
|
|
|
|
label="Internship Year"
|
|
|
|
label="Internship Cycle"
|
|
|
|
options={yearOptions}
|
|
|
|
options={internshipCycleOptions}
|
|
|
|
placeholder={emptyOption}
|
|
|
|
placeholder={emptyOption}
|
|
|
|
required={true}
|
|
|
|
required={true}
|
|
|
|
{...register(`offers.${index}.offersIntern.startYear`, {
|
|
|
|
{...register(`offers.${index}.offersIntern.internshipCycle`, {
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
valueAsNumber: true,
|
|
|
|
})}
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
<FormSelect
|
|
|
|
</div>
|
|
|
|
display="block"
|
|
|
|
</Section>
|
|
|
|
errorMessage={offerFields?.offersIntern?.startYear?.message}
|
|
|
|
<Section title="Compensation Details">
|
|
|
|
label="Internship Year"
|
|
|
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
|
|
|
options={yearOptions}
|
|
|
|
<FormMonthYearPicker
|
|
|
|
placeholder={emptyOption}
|
|
|
|
monthLabel="Date Received"
|
|
|
|
required={true}
|
|
|
|
monthRequired={true}
|
|
|
|
{...register(`offers.${index}.offersIntern.startYear`, {
|
|
|
|
yearLabel=""
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
{...register(`offers.${index}.monthYearReceived`, {
|
|
|
|
valueAsNumber: true,
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
})}
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<FormTextInput
|
|
|
|
<div className="mb-5">
|
|
|
|
endAddOn={
|
|
|
|
<FormMonthYearPicker
|
|
|
|
<FormSelect
|
|
|
|
monthLabel="Date Received"
|
|
|
|
borderStyle="borderless"
|
|
|
|
monthRequired={true}
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
yearLabel=""
|
|
|
|
isLabelHidden={true}
|
|
|
|
{...register(`offers.${index}.monthYearReceived`, {
|
|
|
|
label="Currency"
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
})}
|
|
|
|
{...register(
|
|
|
|
/>
|
|
|
|
`offers.${index}.offersIntern.monthlySalary.currency`,
|
|
|
|
</div>
|
|
|
|
{
|
|
|
|
<div className="mb-5">
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
<FormTextInput
|
|
|
|
},
|
|
|
|
endAddOn={
|
|
|
|
)}
|
|
|
|
<FormSelect
|
|
|
|
/>
|
|
|
|
borderStyle="borderless"
|
|
|
|
}
|
|
|
|
defaultValue={Currency.SGD}
|
|
|
|
endAddOnType="element"
|
|
|
|
isLabelHidden={true}
|
|
|
|
errorMessage={
|
|
|
|
label="Currency"
|
|
|
|
offerFields?.offersIntern?.monthlySalary?.value?.message
|
|
|
|
options={CURRENCY_OPTIONS}
|
|
|
|
}
|
|
|
|
{...register(
|
|
|
|
label="Salary (Monthly)"
|
|
|
|
`offers.${index}.offersIntern.monthlySalary.currency`,
|
|
|
|
placeholder="0"
|
|
|
|
{
|
|
|
|
required={true}
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
startAddOn="$"
|
|
|
|
},
|
|
|
|
startAddOnType="label"
|
|
|
|
)}
|
|
|
|
type="number"
|
|
|
|
/>
|
|
|
|
{...register(`offers.${index}.offersIntern.monthlySalary.value`, {
|
|
|
|
}
|
|
|
|
min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 },
|
|
|
|
endAddOnType="element"
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
errorMessage={
|
|
|
|
valueAsNumber: true,
|
|
|
|
offerFields?.offersIntern?.monthlySalary?.value?.message
|
|
|
|
})}
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
label="Salary (Monthly)"
|
|
|
|
</div>
|
|
|
|
placeholder="0"
|
|
|
|
</Section>
|
|
|
|
required={true}
|
|
|
|
<Section title="Additional Information">
|
|
|
|
startAddOn="$"
|
|
|
|
|
|
|
|
startAddOnType="label"
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
{...register(`offers.${index}.offersIntern.monthlySalary.value`, {
|
|
|
|
|
|
|
|
min: { message: FieldError.NON_NEGATIVE_NUMBER, value: 0 },
|
|
|
|
|
|
|
|
required: FieldError.REQUIRED,
|
|
|
|
|
|
|
|
valueAsNumber: true,
|
|
|
|
|
|
|
|
})}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5">
|
|
|
|
|
|
|
|
<FormTextArea
|
|
|
|
<FormTextArea
|
|
|
|
label="Negotiation Strategy / Interview Performance"
|
|
|
|
label="Negotiation Strategy / Interview Performance"
|
|
|
|
placeholder="e.g. Did well in the behavioral interview. Used competing offers to negotiate for a higher salary."
|
|
|
|
placeholder="e.g. Did well in the behavioral interview. Used competing offers to negotiate for a higher salary."
|
|
|
|
{...register(`offers.${index}.negotiationStrategy`)}
|
|
|
|
{...register(`offers.${index}.negotiationStrategy`)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="mb-5">
|
|
|
|
|
|
|
|
<FormTextArea
|
|
|
|
<FormTextArea
|
|
|
|
label="Comments"
|
|
|
|
label="Comments"
|
|
|
|
placeholder="e.g. Encountered similar questions using the Technical Interview Handbook."
|
|
|
|
placeholder="e.g. Encountered similar questions using the Technical Interview Handbook."
|
|
|
|
{...register(`offers.${index}.comments`)}
|
|
|
|
{...register(`offers.${index}.comments`)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Section>
|
|
|
|
<div className="flex justify-end">
|
|
|
|
{index > 0 && (
|
|
|
|
{index > 0 && (
|
|
|
|
<div className="space-y-4 sm:space-y-6">
|
|
|
|
<Button
|
|
|
|
<HorizontalDivider />
|
|
|
|
icon={TrashIcon}
|
|
|
|
<div className="flex justify-end">
|
|
|
|
label="Delete"
|
|
|
|
<Button
|
|
|
|
variant="secondary"
|
|
|
|
icon={TrashIcon}
|
|
|
|
onClick={() => {
|
|
|
|
label="Delete"
|
|
|
|
remove(index);
|
|
|
|
variant="tertiary"
|
|
|
|
}}
|
|
|
|
onClick={() => {
|
|
|
|
/>
|
|
|
|
remove(index);
|
|
|
|
)}
|
|
|
|
}}
|
|
|
|
</div>
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -466,7 +482,7 @@ function OfferDetailsFormArray({
|
|
|
|
const { append, remove, fields } = fieldArrayValues;
|
|
|
|
const { append, remove, fields } = fieldArrayValues;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<div className="space-y-8">
|
|
|
|
{fields.map((item, index) => {
|
|
|
|
{fields.map((item, index) => {
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div key={item.id}>
|
|
|
|
<div key={item.id}>
|
|
|
@ -483,7 +499,7 @@ function OfferDetailsFormArray({
|
|
|
|
icon={PlusIcon}
|
|
|
|
icon={PlusIcon}
|
|
|
|
label="Add another offer"
|
|
|
|
label="Add another offer"
|
|
|
|
size="lg"
|
|
|
|
size="lg"
|
|
|
|
variant="tertiary"
|
|
|
|
variant="secondary"
|
|
|
|
onClick={() =>
|
|
|
|
onClick={() =>
|
|
|
|
append(
|
|
|
|
append(
|
|
|
|
jobType === JobType.FULLTIME
|
|
|
|
jobType === JobType.FULLTIME
|
|
|
@ -524,7 +540,7 @@ export default function OfferDetailsForm({
|
|
|
|
jobType === JobType.FULLTIME ? JobTypeLabel.INTERN : JobTypeLabel.FULLTIME;
|
|
|
|
jobType === JobType.FULLTIME ? JobTypeLabel.INTERN : JobTypeLabel.FULLTIME;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className="mb-5">
|
|
|
|
<div className="space-y-6">
|
|
|
|
<h5 className="mb-8 text-center text-4xl font-bold text-slate-900">
|
|
|
|
<h5 className="mb-8 text-center text-4xl font-bold text-slate-900">
|
|
|
|
Fill in your offer details
|
|
|
|
Fill in your offer details
|
|
|
|
</h5>
|
|
|
|
</h5>
|
|
|
|