[offers][feat] Use city typeahead for location field

pull/491/head
Ai Ling 3 years ago committed by Bryann Yeap Kok Keong
parent 303b9b1670
commit 6f2e8e7a2d

@ -2,21 +2,6 @@ import { EducationBackgroundType } from './types';
export const emptyOption = '----';
export const locationOptions = [
{
label: 'Singapore, Singapore',
value: 'Singapore, Singapore',
},
{
label: 'New York, US',
value: 'New York, US',
},
{
label: 'San Francisco, US',
value: 'San Francisco, US',
},
];
export const internshipCycleOptions = [
{
label: 'Summer',

@ -51,7 +51,7 @@ export default function DashboardProfileCard({
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400"
/>
{location}
{location.cityName}
</div>
)}
{level && (

@ -26,11 +26,11 @@ import { getCurrentMonth, getCurrentYear } from '~/utils/offers/time';
import { trpc } from '~/utils/trpc';
const defaultOfferValues = {
cityId: '',
comments: '',
companyId: '',
jobTitle: '',
jobType: JobType.FULLTIME,
location: '',
monthYearReceived: {
month: getCurrentMonth() as Month,
year: getCurrentYear(),

@ -7,9 +7,9 @@ import {
educationLevelOptions,
emptyOption,
FieldError,
locationOptions,
} from '~/components/offers/constants';
import type { BackgroundPostData } from '~/components/offers/types';
import CitiesTypeahead from '~/components/shared/CitiesTypeahead';
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
import type { JobTitleType } from '~/components/shared/JobTitles';
import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
@ -102,6 +102,12 @@ function FullTimeJobFields() {
const watchCompanyName = useWatch({
name: 'background.experiences.0.companyName',
});
const watchCityId = useWatch({
name: 'background.experiences.0.cityId',
});
const watchCityName = useWatch({
name: 'background.experiences.0.cityName',
});
return (
<>
@ -166,11 +172,22 @@ function FullTimeJobFields() {
placeholder="e.g. L4, Junior"
{...register(`background.experiences.0.level`)}
/>
<FormSelect
display="block"
<CitiesTypeahead
label="Location"
options={locationOptions}
{...register(`background.experiences.0.location`)}
value={{
id: watchCityId,
label: watchCityName,
value: watchCityId,
}}
onSelect={(option) => {
if (option) {
setValue('background.experiences.0.cityId', option.value);
setValue('background.experiences.0.cityName', option.label);
} else {
setValue('background.experiences.0.cityId', '');
setValue('background.experiences.0.cityName', '');
}
}}
/>
<FormTextInput
errorMessage={experiencesField?.durationInMonths?.message}
@ -202,6 +219,12 @@ function InternshipJobFields() {
const watchCompanyName = useWatch({
name: 'background.experiences.0.companyName',
});
const watchCityId = useWatch({
name: 'background.experiences.0.cityId',
});
const watchCityName = useWatch({
name: 'background.experiences.0.cityName',
});
return (
<>
@ -256,12 +279,22 @@ function InternshipJobFields() {
})}
/>
<Collapsible label="Add more details">
<FormSelect
display="block"
<CitiesTypeahead
label="Location"
options={locationOptions}
placeholder={emptyOption}
{...register(`background.experiences.0.location`)}
value={{
id: watchCityId,
label: watchCityName,
value: watchCityId,
}}
onSelect={(option) => {
if (option) {
setValue('background.experiences.0.cityId', option.value);
setValue('background.experiences.0.cityName', option.label);
} else {
setValue('background.experiences.0.cityId', '');
setValue('background.experiences.0.cityName', '');
}
}}
/>
</Collapsible>
</>

@ -12,6 +12,7 @@ import { TrashIcon } from '@heroicons/react/24/outline';
import { JobType } from '@prisma/client';
import { Button, Dialog, HorizontalDivider } from '@tih/ui';
import CitiesTypeahead from '~/components/shared/CitiesTypeahead';
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
import type { JobTitleType } from '~/components/shared/JobTitles';
import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
@ -25,7 +26,6 @@ import {
emptyOption,
FieldError,
internshipCycleOptions,
locationOptions,
yearOptions,
} from '../../constants';
import FormMonthYearPicker from '../../forms/FormMonthYearPicker';
@ -64,6 +64,12 @@ function FullTimeOfferDetailsForm({
const watchCompanyName = useWatch({
name: `offers.${index}.companyName`,
});
const watchCityId = useWatch({
name: `offers.${index}.cityId`,
});
const watchCityName = useWatch({
name: `offers.${index}.cityName`,
});
const watchCurrency = useWatch({
name: `offers.${index}.offersFullTime.totalCompensation.currency`,
});
@ -119,16 +125,23 @@ function FullTimeOfferDetailsForm({
}
}}
/>
<FormSelect
display="block"
errorMessage={offerFields?.location?.message}
<CitiesTypeahead
label="Location"
options={locationOptions}
placeholder={emptyOption}
required={true}
{...register(`offers.${index}.location`, {
required: FieldError.REQUIRED,
})}
value={{
id: watchCityId,
label: watchCityName,
value: watchCityId,
}}
onSelect={(option) => {
if (option) {
setValue(`offers.${index}.cityId`, option.value);
setValue(`offers.${index}.cityName`, option.label);
} else {
setValue(`offers.${index}.cityId`, '');
setValue(`offers.${index}.cityName`, '');
}
}}
/>
</div>
</FormSection>
@ -308,6 +321,12 @@ function InternshipOfferDetailsForm({
const watchCompanyName = useWatch({
name: `offers.${index}.companyName`,
});
const watchCityId = useWatch({
name: `offers.${index}.cityId`,
});
const watchCityName = useWatch({
name: `offers.${index}.cityName`,
});
return (
<div className="space-y-8 rounded-lg border border-slate-200 p-6 sm:space-y-16 sm:p-8">
@ -341,16 +360,23 @@ function InternshipOfferDetailsForm({
}
}}
/>
<FormSelect
display="block"
errorMessage={offerFields?.location?.message}
<CitiesTypeahead
label="Location"
options={locationOptions}
placeholder={emptyOption}
required={true}
{...register(`offers.${index}.location`, {
required: FieldError.REQUIRED,
})}
value={{
id: watchCityId,
label: watchCityName,
value: watchCityId,
}}
onSelect={(option) => {
if (option) {
setValue(`offers.${index}.cityId`, option.value);
setValue(`offers.${index}.cityName`, option.label);
} else {
setValue(`offers.${index}.cityId`, '');
setValue(`offers.${index}.cityName`, '');
}
}}
/>
</div>
<div className="grid grid-cols-1 gap-y-4 sm:grid-cols-2 sm:gap-6">

@ -100,7 +100,7 @@ export default function OffersTable({
<div className="divide-x-slate-200 col-span-3 flex items-center justify-end space-x-4 divide-x">
<div className="justify-left flex items-center space-x-2">
<span className="sr-only sm:not-sr-only sm:inline">
View all offers in
Display offers in
</span>
<CurrencySelector
handleCurrencyChange={(value: string) => setCurrency(value)}

@ -46,13 +46,14 @@ export type BackgroundPostData = {
};
type ExperiencePostData = {
cityId?: string | null;
cityName?: string | null;
companyId?: string | null;
companyName?: string | null;
durationInMonths?: number | null;
id?: string;
jobType?: string | null;
level?: string | null;
location?: Location | null;
monthlySalary?: Money | null;
title?: string | null;
totalCompensation?: Money | null;
@ -77,12 +78,13 @@ type SpecificYoePostData = {
type SpecificYoe = SpecificYoePostData;
export type OfferPostData = {
cityId: string;
cityName?: string;
comments: string;
companyId: string;
companyName?: string;
id?: string;
jobType: JobType;
location: string;
monthYearReceived: Date;
negotiationStrategy: string;
offersFullTime?: OfferFullTimePostData | null;

@ -36,13 +36,14 @@ export default function OffersEditPage() {
experiences.length === 0
? [{ jobType: JobType.FULLTIME }]
: experiences.map((exp) => ({
cityId: exp.location?.cityId,
cityName: exp.location?.cityName,
companyId: exp.company?.id,
companyName: exp.company?.name,
durationInMonths: exp.durationInMonths,
id: exp.id,
jobType: exp.jobType,
level: exp.level,
location: exp.location,
monthlySalary: exp.monthlySalary,
title: exp.title,
totalCompensation: exp.totalCompensation,
@ -53,12 +54,13 @@ export default function OffersEditPage() {
},
id: data.id,
offers: data.offers.map((offer) => ({
cityId: offer.location.cityId,
cityName: offer.location.cityName,
comments: offer.comments,
companyId: offer.company.id,
companyName: offer.company.name,
id: offer.id,
jobType: offer.jobType,
location: offer.location,
monthYearReceived: convertToMonthYear(offer.monthYearReceived),
negotiationStrategy: offer.negotiationStrategy,
offersFullTime: offer.offersFullTime,

Loading…
Cancel
Save