From 1eed5227c436114e2e15574925d30f77772d80e1 Mon Sep 17 00:00:00 2001 From: Ai Ling Date: Wed, 12 Oct 2022 13:09:23 +0800 Subject: [PATCH] [offers][feat] Add error messages for text input fields --- .../src/components/offers/OffersNavigation.ts | 1 - .../portal/src/components/offers/constants.ts | 4 + .../offers/forms/OfferDetailsForm.tsx | 82 ++++++++++++------- apps/portal/src/components/offers/types.ts | 15 +++- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/apps/portal/src/components/offers/OffersNavigation.ts b/apps/portal/src/components/offers/OffersNavigation.ts index a1974d94..cfa314dc 100644 --- a/apps/portal/src/components/offers/OffersNavigation.ts +++ b/apps/portal/src/components/offers/OffersNavigation.ts @@ -1,7 +1,6 @@ import type { ProductNavigationItems } from '~/components/global/ProductNavigation'; const navigation: ProductNavigationItems = [ - { href: '/offers', name: 'Home' }, { href: '/offers/submit', name: 'Benchmark your offer' }, ]; diff --git a/apps/portal/src/components/offers/constants.ts b/apps/portal/src/components/offers/constants.ts index a5dc2706..9188606a 100644 --- a/apps/portal/src/components/offers/constants.ts +++ b/apps/portal/src/components/offers/constants.ts @@ -134,3 +134,7 @@ export const educationFieldOptions = [ value: 'Business Analytics', }, ]; + +export enum FieldError { + required = 'Please fill in this field.', +} diff --git a/apps/portal/src/components/offers/forms/OfferDetailsForm.tsx b/apps/portal/src/components/offers/forms/OfferDetailsForm.tsx index 6348360f..b654f89f 100644 --- a/apps/portal/src/components/offers/forms/OfferDetailsForm.tsx +++ b/apps/portal/src/components/offers/forms/OfferDetailsForm.tsx @@ -16,12 +16,16 @@ import FormTextArea from './components/FormTextArea'; import FormTextInput from './components/FormTextInput'; import { companyOptions, + FieldError, internshipCycleOptions, locationOptions, titleOptions, yearOptions, } from '../constants'; -import type { OfferDetailsFormData } from '../types'; +import type { + FullTimeOfferDetailsFormData, + InternshipOfferDetailsFormData, +} from '../types'; import { JobType } from '../types'; import { CURRENCY_OPTIONS } from '../../../utils/offers/currency/CurrencyEnum'; @@ -34,10 +38,12 @@ function FullTimeOfferDetailsForm({ index, remove, }: FullTimeOfferDetailsFormProps) { - const { register } = useFormContext<{ - offers: Array; + const { register, formState } = useFormContext<{ + offers: Array; }>(); + const jobFields = formState.errors.offers?.[index]?.job; + return (
@@ -47,15 +53,16 @@ function FullTimeOfferDetailsForm({ options={titleOptions} required={true} {...register(`offers.${index}.job.title`, { - required: true, + required: FieldError.required, })} />
@@ -65,13 +72,18 @@ function FullTimeOfferDetailsForm({ label="Company" options={companyOptions} required={true} - {...register(`offers.${index}.companyId`, { required: true })} + {...register(`offers.${index}.companyId`, { + required: FieldError.required, + })} />
@@ -80,10 +92,14 @@ function FullTimeOfferDetailsForm({ label="Location" options={locationOptions} required={true} - {...register(`offers.${index}.location`, { required: true })} + {...register(`offers.${index}.location`, { + required: FieldError.required, + })} />
@@ -95,11 +111,12 @@ function FullTimeOfferDetailsForm({ label="Currency" options={CURRENCY_OPTIONS} {...register(`offers.${index}.job.totalCompensation.currency`, { - required: true, + required: FieldError.required, })} /> } endAddOnType="element" + errorMessage={jobFields?.totalCompensation?.value?.message} label="Total Compensation (Annual)" placeholder="0.00" required={true} @@ -107,7 +124,7 @@ function FullTimeOfferDetailsForm({ startAddOnType="label" type="number" {...register(`offers.${index}.job.totalCompensation.value`, { - required: true, + required: FieldError.required, valueAsNumber: true, })} /> @@ -121,11 +138,12 @@ function FullTimeOfferDetailsForm({ label="Currency" options={CURRENCY_OPTIONS} {...register(`offers.${index}.job.base.currency`, { - required: true, + required: FieldError.required, })} /> } endAddOnType="element" + errorMessage={jobFields?.base?.value?.message} label="Base Salary (Annual)" placeholder="0.00" required={true} @@ -133,7 +151,7 @@ function FullTimeOfferDetailsForm({ startAddOnType="label" type="number" {...register(`offers.${index}.job.base.value`, { - required: true, + required: FieldError.required, valueAsNumber: true, })} /> @@ -145,11 +163,12 @@ function FullTimeOfferDetailsForm({ label="Currency" options={CURRENCY_OPTIONS} {...register(`offers.${index}.job.bonus.currency`, { - required: true, + required: FieldError.required, })} /> } endAddOnType="element" + errorMessage={jobFields?.bonus?.value?.message} label="Bonus (Annual)" placeholder="0.00" required={true} @@ -157,7 +176,7 @@ function FullTimeOfferDetailsForm({ startAddOnType="label" type="number" {...register(`offers.${index}.job.bonus.value`, { - required: true, + required: FieldError.required, valueAsNumber: true, })} /> @@ -171,11 +190,12 @@ function FullTimeOfferDetailsForm({ label="Currency" options={CURRENCY_OPTIONS} {...register(`offers.${index}.job.stocks.currency`, { - required: true, + required: FieldError.required, })} /> } endAddOnType="element" + errorMessage={jobFields?.stocks?.value?.message} label="Stocks (Annual)" placeholder="0.00" required={true} @@ -183,7 +203,7 @@ function FullTimeOfferDetailsForm({ startAddOnType="label" type="number" {...register(`offers.${index}.job.stocks.value`, { - required: true, + required: FieldError.required, valueAsNumber: true, })} /> @@ -264,10 +284,12 @@ function InternshipOfferDetailsForm({ index, remove, }: InternshipOfferDetailsFormProps) { - const { register } = useFormContext<{ - offers: Array; + const { register, formState } = useFormContext<{ + offers: Array; }>(); + const jobFields = formState.errors.offers?.[index]?.job; + return (
@@ -278,16 +300,17 @@ function InternshipOfferDetailsForm({ required={true} {...register(`offers.${index}.job.title`, { minLength: 1, - required: true, + required: FieldError.required, })} />
@@ -298,7 +321,7 @@ function InternshipOfferDetailsForm({ options={companyOptions} required={true} {...register(`offers.${index}.companyId`, { - required: true, + required: FieldError.required, })} />
@@ -318,7 +341,7 @@ function InternshipOfferDetailsForm({ options={internshipCycleOptions} required={true} {...register(`offers.${index}.job.internshipCycle`, { - required: true, + required: FieldError.required, })} />

Date received:

@@ -346,11 +371,12 @@ function InternshipOfferDetailsForm({ label="Currency" options={CURRENCY_OPTIONS} {...register(`offers.${index}.job.monthlySalary.currency`, { - required: true, + required: FieldError.required, })} /> } endAddOnType="element" + errorMessage={jobFields?.monthlySalary?.value?.message} label="Salary (Monthly)" placeholder="0.00" required={true} @@ -358,7 +384,7 @@ function InternshipOfferDetailsForm({ startAddOnType="label" type="number" {...register(`offers.${index}.job.monthlySalary.value`, { - required: true, + required: FieldError.required, valueAsNumber: true, })} /> diff --git a/apps/portal/src/components/offers/types.ts b/apps/portal/src/components/offers/types.ts index dfc46b6b..4bbf44dd 100644 --- a/apps/portal/src/components/offers/types.ts +++ b/apps/portal/src/components/offers/types.ts @@ -43,16 +43,27 @@ type InternshipJobData = { title: string; }; -export type OfferDetailsFormData = { +type OfferDetailsGeneralData = { comments: string; companyId: string; - job: FullTimeJobData | InternshipJobData; jobType: string; location: string; monthYearReceived: MonthYear; negotiationStrategy: string; }; +export type FullTimeOfferDetailsFormData = OfferDetailsGeneralData & { + job: FullTimeJobData; +}; + +export type InternshipOfferDetailsFormData = OfferDetailsGeneralData & { + job: InternshipJobData; +}; + +export type OfferDetailsFormData = + | FullTimeOfferDetailsFormData + | InternshipOfferDetailsFormData; + export type OfferDetailsPostData = Omit< OfferDetailsFormData, 'monthYearReceived'