diff --git a/apps/portal/src/components/offers/forms/BackgroundForm.tsx b/apps/portal/src/components/offers/forms/BackgroundForm.tsx
index 0acbbe69..02d64af7 100644
--- a/apps/portal/src/components/offers/forms/BackgroundForm.tsx
+++ b/apps/portal/src/components/offers/forms/BackgroundForm.tsx
@@ -1,9 +1,9 @@
import { useFormContext, useWatch } from 'react-hook-form';
import { Collapsible, RadioList } from '@tih/ui';
-import FormRadioList from './FormRadioList';
-import FormSelect from './FormSelect';
-import FormTextInput from './FormTextInput';
+import FormRadioList from './components/FormRadioList';
+import FormSelect from './components/FormSelect';
+import FormTextInput from './components/FormTextInput';
import {
companyOptions,
educationFieldOptions,
diff --git a/apps/portal/src/components/offers/forms/OfferAnalysis.tsx b/apps/portal/src/components/offers/forms/OfferAnalysis.tsx
index 3147bdc2..b0b7133c 100644
--- a/apps/portal/src/components/offers/forms/OfferAnalysis.tsx
+++ b/apps/portal/src/components/offers/forms/OfferAnalysis.tsx
@@ -86,8 +86,7 @@ export default function OfferAnalysis() {
Result
-
-
+
;
+ offers: Array;
}>();
return (
@@ -81,10 +82,7 @@ function FullTimeOfferDetailsForm({
required={true}
{...register(`offers.${index}.location`, { required: true })}
/>
-
@@ -121,7 +119,9 @@ function FullTimeOfferDetailsForm({
isLabelHidden={true}
label="Currency"
options={CURRENCY_OPTIONS}
- {...register(`offers.${index}.job.base.currency`)}
+ {...register(`offers.${index}.job.base.currency`, {
+ required: true,
+ })}
/>
}
endAddOnType="element"
@@ -131,7 +131,7 @@ function FullTimeOfferDetailsForm({
startAddOn="$"
startAddOnType="label"
type="number"
- {...register(`offers.${index}.job.base.value`)}
+ {...register(`offers.${index}.job.base.value`, { required: true })}
/>
}
endAddOnType="element"
@@ -150,7 +152,7 @@ function FullTimeOfferDetailsForm({
startAddOn="$"
startAddOnType="label"
type="number"
- {...register(`offers.${index}.job.bonus.value`)}
+ {...register(`offers.${index}.job.bonus.value`, { required: true })}
/>
@@ -161,7 +163,9 @@ function FullTimeOfferDetailsForm({
isLabelHidden={true}
label="Currency"
options={CURRENCY_OPTIONS}
- {...register(`offers.${index}.job.stocks.currency`)}
+ {...register(`offers.${index}.job.stocks.currency`, {
+ required: true,
+ })}
/>
}
endAddOnType="element"
@@ -171,7 +175,7 @@ function FullTimeOfferDetailsForm({
startAddOn="$"
startAddOnType="label"
type="number"
- {...register(`offers.${index}.job.stocks.value`)}
+ {...register(`offers.${index}.job.stocks.value`, { required: true })}
/>
@@ -251,7 +255,7 @@ function InternshipOfferDetailsForm({
remove,
}: InternshipOfferDetailsFormProps) {
const { register } = useFormContext<{
- offers: Array;
+ offers: Array;
}>();
return (
@@ -262,13 +266,19 @@ function InternshipOfferDetailsForm({
label="Title"
options={titleOptions}
required={true}
- {...register(`offers.${index}.job.title`)}
+ {...register(`offers.${index}.job.title`, {
+ minLength: 1,
+ required: true,
+ })}
/>
@@ -289,13 +299,7 @@ function InternshipOfferDetailsForm({
{...register(`offers.${index}.location`)}
/>
-
-
+
+
;
+
+type FormMonthYearPickerProps = Omit<
+ MonthYearPickerProps,
+ 'onChange' | 'value'
+> & {
+ name: string;
+};
+
+function FormMonthYearPickerWithRef({
+ name,
+ ...rest
+}: FormMonthYearPickerProps) {
+ const { setValue } = useFormContext();
+
+ const value = useWatch({
+ defaultValue: { month: getCurrentMonth(), year: getCurrentYear() },
+ name,
+ });
+
+ return (
+ {
+ setValue(name, val);
+ }}
+ />
+ );
+}
+
+const FormMonthYearPicker = forwardRef(FormMonthYearPickerWithRef);
+
+export default FormMonthYearPicker;
diff --git a/apps/portal/src/components/offers/forms/FormRadioList.tsx b/apps/portal/src/components/offers/forms/components/FormRadioList.tsx
similarity index 100%
rename from apps/portal/src/components/offers/forms/FormRadioList.tsx
rename to apps/portal/src/components/offers/forms/components/FormRadioList.tsx
diff --git a/apps/portal/src/components/offers/forms/FormSelect.tsx b/apps/portal/src/components/offers/forms/components/FormSelect.tsx
similarity index 100%
rename from apps/portal/src/components/offers/forms/FormSelect.tsx
rename to apps/portal/src/components/offers/forms/components/FormSelect.tsx
diff --git a/apps/portal/src/components/offers/forms/FormTextArea.tsx b/apps/portal/src/components/offers/forms/components/FormTextArea.tsx
similarity index 100%
rename from apps/portal/src/components/offers/forms/FormTextArea.tsx
rename to apps/portal/src/components/offers/forms/components/FormTextArea.tsx
diff --git a/apps/portal/src/components/offers/forms/FormTextInput.tsx b/apps/portal/src/components/offers/forms/components/FormTextInput.tsx
similarity index 100%
rename from apps/portal/src/components/offers/forms/FormTextInput.tsx
rename to apps/portal/src/components/offers/forms/components/FormTextInput.tsx
diff --git a/apps/portal/src/components/offers/types.ts b/apps/portal/src/components/offers/types.ts
index 17bda427..b514744e 100644
--- a/apps/portal/src/components/offers/types.ts
+++ b/apps/portal/src/components/offers/types.ts
@@ -3,6 +3,8 @@
* Offer Profile
*/
+import type { MonthYear } from '../shared/MonthYearPicker';
+
export enum JobType {
FullTime = 'FULLTIME',
Internship = 'INTERNSHIP',
@@ -33,16 +35,6 @@ type FullTimeJobData = {
totalCompensation: Money;
};
-export type FullTimeOfferFormData = {
- comments: string;
- companyId: string;
- job: FullTimeJobData;
- jobType: string;
- location: string;
- monthYearReceived: string;
- negotiationStrategy: string;
-};
-
type InternshipJobData = {
internshipCycle: string;
monthlySalary: Money;
@@ -51,18 +43,16 @@ type InternshipJobData = {
title: string;
};
-export type InternshipOfferFormData = {
+export type OfferDetailsFormData = {
comments: string;
companyId: string;
- job: InternshipJobData;
+ job: FullTimeJobData | InternshipJobData;
jobType: string;
location: string;
- monthYearReceived: string;
+ monthYearReceived: MonthYear;
negotiationStrategy: string;
};
-type OfferDetailsFormData = FullTimeOfferFormData | InternshipOfferFormData;
-
type SpecificYoe = {
domain: string;
yoe: number;
diff --git a/apps/portal/src/components/offers/util/time/index.tsx b/apps/portal/src/components/offers/util/time/index.tsx
index 86f21ab9..c13a6efe 100644
--- a/apps/portal/src/components/offers/util/time/index.tsx
+++ b/apps/portal/src/components/offers/util/time/index.tsx
@@ -1,3 +1,7 @@
+import { getMonth, getYear } from 'date-fns';
+
+import type { MonthYear } from '~/components/shared/MonthYearPicker';
+
export function formatDate(value: Date | number | string) {
const date = new Date(value);
// Const day = date.toLocaleString('default', { day: '2-digit' });
@@ -5,3 +9,17 @@ export function formatDate(value: Date | number | string) {
const year = date.toLocaleString('default', { year: 'numeric' });
return `${month} ${year}`;
}
+
+export function formatMonthYear({ month, year }: MonthYear) {
+ const monthString = month < 10 ? month.toString() : `0${month}`;
+ const yearString = year.toString();
+ return `${monthString}/${yearString}`;
+}
+
+export function getCurrentMonth() {
+ return getMonth(Date.now());
+}
+
+export function getCurrentYear() {
+ return getYear(Date.now());
+}
diff --git a/apps/portal/src/pages/offers/index.tsx b/apps/portal/src/pages/offers/index.tsx
index 27166716..c4dfe8b5 100644
--- a/apps/portal/src/pages/offers/index.tsx
+++ b/apps/portal/src/pages/offers/index.tsx
@@ -3,9 +3,11 @@ import { Select } from '@tih/ui';
import OffersTable from '~/components/offers/OffersTable';
import OffersTitle from '~/components/offers/OffersTitle';
+import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
export default function OffersHomePage() {
const [jobTitleFilter, setjobTitleFilter] = useState('Software engineers');
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const [companyFilter, setCompanyFilter] = useState('All companies');
return (
@@ -13,7 +15,7 @@ export default function OffersHomePage() {
-
+
Viewing offers for
diff --git a/apps/portal/src/pages/offers/submit.tsx b/apps/portal/src/pages/offers/submit.tsx
index b85e098c..05b25555 100644
--- a/apps/portal/src/pages/offers/submit.tsx
+++ b/apps/portal/src/pages/offers/submit.tsx
@@ -9,6 +9,8 @@ import OfferAnalysis from '~/components/offers/forms/OfferAnalysis';
import OfferDetailsForm from '~/components/offers/forms/OfferDetailsForm';
import OfferProfileSave from '~/components/offers/forms/OfferProfileSave';
import type { SubmitOfferFormData } from '~/components/offers/types';
+import { getCurrentMonth, getCurrentYear } from '~/components/offers/util/time';
+import type { Month } from '~/components/shared/MonthYearPicker';
function Breadcrumbs() {
return (
@@ -23,53 +25,69 @@ const defaultOfferValues = {
{
comments: '',
companyId: '',
- job: {
- base: {
- currency: 'USD',
- value: 0,
- },
- bonus: {
- currency: 'USD',
- value: 0,
- },
- level: '',
- specialization: '',
- stocks: {
- currency: 'USD',
- value: 0,
- },
- title: '',
- totalCompensation: {
- currency: 'USD',
- value: 0,
- },
- },
+ job: {},
jobType: 'FULLTIME',
location: '',
- monthYearReceived: '',
+ monthYearReceived: {
+ month: getCurrentMonth() as Month,
+ year: getCurrentYear(),
+ },
negotiationStrategy: '',
},
],
};
+type FormStep = {
+ component: JSX.Element;
+ hasNext: boolean;
+ hasPrevious: boolean;
+};
+
export default function OffersSubmissionPage() {
const [formStep, setFormStep] = useState(0);
const formMethods = useForm
({
defaultValues: defaultOfferValues,
+ mode: 'all',
});
+ const { handleSubmit, trigger } = formMethods;
- const nextStep = () => setFormStep(formStep + 1);
- const previousStep = () => setFormStep(formStep - 1);
-
- const formComponents = [
- ,
- ,
- ,
- ,
+ const formSteps: Array = [
+ {
+ component: ,
+ hasNext: true,
+ hasPrevious: false,
+ },
+ {
+ component: ,
+ hasNext: false,
+ hasPrevious: true,
+ },
+ { component: , hasNext: true, hasPrevious: false },
+ {
+ component: ,
+ hasNext: false,
+ hasPrevious: false,
+ },
];
+ const nextStep = async (currStep: number) => {
+ if (currStep === 0) {
+ const result = await trigger('offers');
+ if (!result) {
+ return;
+ }
+ }
+ setFormStep(formStep + 1);
+ };
+
+ const previousStep = () => setFormStep(formStep - 1);
+
const onSubmit: SubmitHandler = async () => {
- nextStep();
+ const result = await trigger();
+ if (!result) {
+ return;
+ }
+ setFormStep(formStep + 1);
};
return (
@@ -78,16 +96,17 @@ export default function OffersSubmissionPage() {