From 7b960a0b87c6f82a247697fa96872e9174d14c71 Mon Sep 17 00:00:00 2001
From: Bryann Yeap Kok Keong
Date: Mon, 31 Oct 2022 14:09:57 +0800
Subject: [PATCH 1/8] [offers][chore] Change location in schema
---
apps/portal/prisma/schema.prisma | 8 +-
.../router/offers/offers-profile-router.ts | 73 +++++++++++++++++--
2 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/apps/portal/prisma/schema.prisma b/apps/portal/prisma/schema.prisma
index b2820c3c..b6873fde 100644
--- a/apps/portal/prisma/schema.prisma
+++ b/apps/portal/prisma/schema.prisma
@@ -131,6 +131,8 @@ model City {
stateId String
state State @relation(fields: [stateId], references: [id])
questionsQuestionEncounters QuestionsQuestionEncounter[]
+ OffersExperience OffersExperience[]
+ OffersOffer OffersOffer[]
@@unique([name, stateId])
}
@@ -265,7 +267,8 @@ model OffersExperience {
// Add more fields
durationInMonths Int?
- location String?
+ location City? @relation(fields: [cityId], references: [id])
+ cityId String?
// FULLTIME fields
level String?
@@ -348,8 +351,9 @@ model OffersOffer {
company Company @relation(fields: [companyId], references: [id])
companyId String
+ location City @relation(fields: [cityId], references: [id])
+ cityId String
monthYearReceived DateTime
- location String
negotiationStrategy String
comments String
diff --git a/apps/portal/src/server/router/offers/offers-profile-router.ts b/apps/portal/src/server/router/offers/offers-profile-router.ts
index 48c8fb74..7e4ed3c5 100644
--- a/apps/portal/src/server/router/offers/offers-profile-router.ts
+++ b/apps/portal/src/server/router/offers/offers-profile-router.ts
@@ -110,12 +110,12 @@ export const offersProfileRouter = createRouter()
async resolve({ ctx, input }) {
const profile = await ctx.prisma.offersProfile.findFirst({
where: {
- id: input.profileId
- }
- })
+ id: input.profileId,
+ },
+ });
- return profile?.editToken === input.token
- }
+ return profile?.editToken === input.token;
+ },
})
.query('listOne', {
input: z.object({
@@ -133,6 +133,15 @@ export const offersProfileRouter = createRouter()
topSimilarOffers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -150,6 +159,15 @@ export const offersProfileRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -165,6 +183,15 @@ export const offersProfileRouter = createRouter()
topSimilarOffers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -182,6 +209,15 @@ export const offersProfileRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -195,6 +231,15 @@ export const offersProfileRouter = createRouter()
overallHighestOffer: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -220,6 +265,15 @@ export const offersProfileRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
monthlySalary: true,
totalCompensation: true,
},
@@ -237,6 +291,15 @@ export const offersProfileRouter = createRouter()
offers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
baseSalary: true,
From b5b42ced4b667c92c43ea66c4686e9e09f6b90bc Mon Sep 17 00:00:00 2001
From: Bryann Yeap Kok Keong
Date: Mon, 31 Oct 2022 14:47:05 +0800
Subject: [PATCH 2/8] Include City, State, and Country in profileDtoMapper
params
---
apps/portal/src/mappers/offers-mappers.ts | 24 +++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/apps/portal/src/mappers/offers-mappers.ts b/apps/portal/src/mappers/offers-mappers.ts
index 7ce52626..a2a7c80f 100644
--- a/apps/portal/src/mappers/offers-mappers.ts
+++ b/apps/portal/src/mappers/offers-mappers.ts
@@ -1,5 +1,7 @@
import type {
+ City,
Company,
+ Country,
OffersAnalysis,
OffersAnalysisUnit,
OffersBackground,
@@ -12,6 +14,7 @@ import type {
OffersProfile,
OffersReply,
OffersSpecificYoe,
+ State,
User,
} from '@prisma/client';
import { JobType } from '@prisma/client';
@@ -449,6 +452,7 @@ export const profileDtoMapper = (
topSimilarOffers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -459,7 +463,14 @@ export const profileDtoMapper = (
background:
| (OffersBackground & {
experiences: Array<
- OffersExperience & { company: Company | null }
+ OffersExperience & {
+ company: Company | null;
+ location:
+ | (City & {
+ state: State & { country: Country };
+ })
+ | null;
+ }
>;
})
| null;
@@ -472,6 +483,7 @@ export const profileDtoMapper = (
topSimilarOffers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -482,7 +494,12 @@ export const profileDtoMapper = (
background:
| (OffersBackground & {
experiences: Array<
- OffersExperience & { company: Company | null }
+ OffersExperience & {
+ company: Company | null;
+ location:
+ | (City & { state: State & { country: Country } })
+ | null;
+ }
>;
})
| null;
@@ -492,6 +509,7 @@ export const profileDtoMapper = (
};
overallHighestOffer: OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -508,6 +526,7 @@ export const profileDtoMapper = (
experiences: Array<
OffersExperience & {
company: Company | null;
+ location: (City & { state: State & { country: Country } }) | null;
monthlySalary: OffersCurrency | null;
totalCompensation: OffersCurrency | null;
}
@@ -525,6 +544,7 @@ export const profileDtoMapper = (
offers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & {
baseSalary: OffersCurrency | null;
From 02a90d27361b7fb3acbf673acc373f04cc99f21c Mon Sep 17 00:00:00 2001
From: Bryann Yeap Kok Keong
Date: Wed, 2 Nov 2022 04:09:11 +0800
Subject: [PATCH 3/8] [offers][chore] Change backend endpoints to new location
field
---
apps/portal/src/mappers/offers-mappers.ts | 72 ++++++++--
.../router/offers/offers-analysis-router.ts | 128 +++++++++++++++++-
.../offers/offers-user-profile-router.ts | 9 ++
.../portal/src/server/router/offers/offers.ts | 8 +-
apps/portal/src/types/offers.d.ts | 20 ++-
5 files changed, 217 insertions(+), 20 deletions(-)
diff --git a/apps/portal/src/mappers/offers-mappers.ts b/apps/portal/src/mappers/offers-mappers.ts
index a2a7c80f..e0cea797 100644
--- a/apps/portal/src/mappers/offers-mappers.ts
+++ b/apps/portal/src/mappers/offers-mappers.ts
@@ -31,6 +31,7 @@ import type {
Education,
Experience,
GetOffersResponse,
+ Location,
OffersCompany,
Paging,
Profile,
@@ -45,6 +46,7 @@ import type {
const analysisOfferDtoMapper = (
offer: OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -52,7 +54,14 @@ const analysisOfferDtoMapper = (
profile: OffersProfile & {
background:
| (OffersBackground & {
- experiences: Array;
+ experiences: Array<
+ OffersExperience & {
+ company: Company | null;
+ location:
+ | (City & { state: State & { country: Country } })
+ | null;
+ }
+ >;
})
| null;
};
@@ -71,7 +80,7 @@ const analysisOfferDtoMapper = (
},
jobType: offer.jobType,
level: offer.offersFullTime?.level ?? '',
- location: offer.location,
+ location: locationDtoMapper(offer.location),
monthYearReceived: offer.monthYearReceived,
negotiationStrategy: offer.negotiationStrategy,
previousCompanies:
@@ -120,6 +129,7 @@ const analysisUnitDtoMapper = (
topSimilarOffers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -128,7 +138,12 @@ const analysisUnitDtoMapper = (
background:
| (OffersBackground & {
experiences: Array<
- OffersExperience & { company: Company | null }
+ OffersExperience & {
+ company: Company | null;
+ location:
+ | (City & { state: State & { country: Country } })
+ | null;
+ }
>;
})
| null;
@@ -151,6 +166,7 @@ const analysisUnitDtoMapper = (
const analysisHighestOfferDtoMapper = (
offer: OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -162,7 +178,7 @@ const analysisHighestOfferDtoMapper = (
company: offersCompanyDtoMapper(offer.company),
id: offer.id,
level: offer.offersFullTime?.level ?? '',
- location: offer.location,
+ location: locationDtoMapper(offer.location),
totalYoe: offer.profile.background?.totalYoe ?? -1,
};
return analysisHighestOfferDto;
@@ -176,6 +192,7 @@ export const profileAnalysisDtoMapper = (
topSimilarOffers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -186,7 +203,12 @@ export const profileAnalysisDtoMapper = (
background:
| (OffersBackground & {
experiences: Array<
- OffersExperience & { company: Company | null }
+ OffersExperience & {
+ company: Company | null;
+ location:
+ | (City & { state: State & { country: Country } })
+ | null;
+ }
>;
})
| null;
@@ -199,6 +221,7 @@ export const profileAnalysisDtoMapper = (
topSimilarOffers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -209,7 +232,12 @@ export const profileAnalysisDtoMapper = (
background:
| (OffersBackground & {
experiences: Array<
- OffersExperience & { company: Company | null }
+ OffersExperience & {
+ company: Company | null;
+ location:
+ | (City & { state: State & { country: Country } })
+ | null;
+ }
>;
})
| null;
@@ -219,6 +247,7 @@ export const profileAnalysisDtoMapper = (
};
overallHighestOffer: OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -250,6 +279,23 @@ export const profileAnalysisDtoMapper = (
return profileAnalysisDto;
};
+export const locationDtoMapper = (
+ city: City & { state: State & { country: Country } },
+) => {
+ const { state } = city;
+ const { country } = state;
+ const locationDto: Location = {
+ cityId: city.id,
+ cityName: city.name,
+ countryCode: country.code,
+ countryId: country.id,
+ countryName: country.name,
+ stateId: state.id,
+ stateName: state.name,
+ };
+ return locationDto;
+};
+
export const valuationDtoMapper = (currency: {
baseCurrency: string;
baseValue: number;
@@ -303,6 +349,7 @@ export const educationDtoMapper = (education: {
export const experienceDtoMapper = (
experience: OffersExperience & {
company: Company | null;
+ location: (City & { state: State & { country: Country } }) | null;
monthlySalary: OffersCurrency | null;
totalCompensation: OffersCurrency | null;
},
@@ -315,7 +362,10 @@ export const experienceDtoMapper = (
id: experience.id,
jobType: experience.jobType,
level: experience.level,
- location: experience.location,
+ location:
+ experience.location != null
+ ? locationDtoMapper(experience.location)
+ : null,
monthlySalary: experience.monthlySalary
? valuationDtoMapper(experience.monthlySalary)
: null,
@@ -348,6 +398,7 @@ export const backgroundDtoMapper = (
experiences: Array<
OffersExperience & {
company: Company | null;
+ location: (City & { state: State & { country: Country } }) | null;
monthlySalary: OffersCurrency | null;
totalCompensation: OffersCurrency | null;
}
@@ -386,6 +437,7 @@ export const backgroundDtoMapper = (
export const profileOfferDtoMapper = (
offer: OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & {
baseSalary: OffersCurrency | null;
@@ -402,7 +454,7 @@ export const profileOfferDtoMapper = (
company: offersCompanyDtoMapper(offer.company),
id: offer.id,
jobType: offer.jobType,
- location: offer.location,
+ location: locationDtoMapper(offer.location),
monthYearReceived: offer.monthYearReceived,
negotiationStrategy: offer.negotiationStrategy,
offersFullTime: offer.offersFullTime,
@@ -676,6 +728,7 @@ export const getUserProfileResponseMapper = (
offers: Array<
OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -711,6 +764,7 @@ export const getUserProfileResponseMapper = (
const userProfileOfferDtoMapper = (
offer: OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
| (OffersFullTime & { totalCompensation: OffersCurrency })
| null;
@@ -729,7 +783,7 @@ const userProfileOfferDtoMapper = (
},
jobType: offer.jobType,
level: offer.offersFullTime?.level ?? '',
- location: offer.location,
+ location: locationDtoMapper(offer.location),
monthYearReceived: offer.monthYearReceived,
title:
offer.jobType === JobType.FULLTIME
diff --git a/apps/portal/src/server/router/offers/offers-analysis-router.ts b/apps/portal/src/server/router/offers/offers-analysis-router.ts
index b42da967..f86cdc75 100644
--- a/apps/portal/src/server/router/offers/offers-analysis-router.ts
+++ b/apps/portal/src/server/router/offers/offers-analysis-router.ts
@@ -1,12 +1,15 @@
import { z } from 'zod';
import type {
+ City,
Company,
+ Country,
OffersBackground,
OffersCurrency,
OffersFullTime,
OffersIntern,
OffersOffer,
OffersProfile,
+ State,
} from '@prisma/client';
import { TRPCError } from '@trpc/server';
@@ -16,8 +19,14 @@ import { createRouter } from '../context';
type Offer = OffersOffer & {
company: Company;
+ location: City & { state: State & { country: Country } };
offersFullTime:
- | (OffersFullTime & { totalCompensation: OffersCurrency })
+ | (OffersFullTime & {
+ baseSalary: OffersCurrency | null;
+ bonus: OffersCurrency | null;
+ stocks: OffersCurrency | null;
+ totalCompensation: OffersCurrency;
+ })
| null;
offersIntern: (OffersIntern & { monthlySalary: OffersCurrency }) | null;
profile: OffersProfile & { background: OffersBackground | null };
@@ -60,6 +69,15 @@ export const offersAnalysisRouter = createRouter()
topSimilarOffers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -77,6 +95,15 @@ export const offersAnalysisRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -92,6 +119,15 @@ export const offersAnalysisRouter = createRouter()
topSimilarOffers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -109,6 +145,15 @@ export const offersAnalysisRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -122,6 +167,15 @@ export const offersAnalysisRouter = createRouter()
overallHighestOffer: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -169,6 +223,15 @@ export const offersAnalysisRouter = createRouter()
const offers = await ctx.prisma.offersOffer.findMany({
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
baseSalary: true,
@@ -235,6 +298,15 @@ export const offersAnalysisRouter = createRouter()
let similarOffers = await ctx.prisma.offersOffer.findMany({
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -252,6 +324,15 @@ export const offersAnalysisRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -434,6 +515,15 @@ export const offersAnalysisRouter = createRouter()
topSimilarOffers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -451,6 +541,15 @@ export const offersAnalysisRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -466,6 +565,15 @@ export const offersAnalysisRouter = createRouter()
topSimilarOffers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
@@ -483,6 +591,15 @@ export const offersAnalysisRouter = createRouter()
experiences: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
},
},
},
@@ -496,6 +613,15 @@ export const offersAnalysisRouter = createRouter()
overallHighestOffer: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
diff --git a/apps/portal/src/server/router/offers/offers-user-profile-router.ts b/apps/portal/src/server/router/offers/offers-user-profile-router.ts
index 48994044..ae816261 100644
--- a/apps/portal/src/server/router/offers/offers-user-profile-router.ts
+++ b/apps/portal/src/server/router/offers/offers-user-profile-router.ts
@@ -57,6 +57,15 @@ export const offersUserProfileRouter = createProtectedRouter()
offers: {
include: {
company: true,
+ location: {
+ include: {
+ state: {
+ include: {
+ country: true,
+ },
+ },
+ },
+ },
offersFullTime: {
include: {
totalCompensation: true,
diff --git a/apps/portal/src/server/router/offers/offers.ts b/apps/portal/src/server/router/offers/offers.ts
index 86cd29ef..916dcb57 100644
--- a/apps/portal/src/server/router/offers/offers.ts
+++ b/apps/portal/src/server/router/offers/offers.ts
@@ -43,12 +43,12 @@ const getYoeRange = (yoeCategory: number) => {
export const offersRouter = createRouter().query('list', {
input: z.object({
+ cityId: z.string(),
companyId: z.string().nullish(),
currency: z.string().nullish(),
dateEnd: z.date().nullish(),
dateStart: z.date().nullish(),
limit: z.number().positive(),
- location: z.string(),
offset: z.number().nonnegative(),
salaryMax: z.number().nonnegative().nullish(),
salaryMin: z.number().nonnegative().nullish(),
@@ -132,8 +132,7 @@ export const offersRouter = createRouter().query('list', {
where: {
AND: [
{
- location:
- input.location.length === 0 ? undefined : input.location,
+ cityId: input.cityId.length === 0 ? undefined : input.cityId,
},
{
offersIntern: {
@@ -246,8 +245,7 @@ export const offersRouter = createRouter().query('list', {
where: {
AND: [
{
- location:
- input.location.length === 0 ? undefined : input.location,
+ cityId: input.cityId.length === 0 ? undefined : input.cityId,
},
{
offersIntern: {
diff --git a/apps/portal/src/types/offers.d.ts b/apps/portal/src/types/offers.d.ts
index 2ff82a16..3dcba938 100644
--- a/apps/portal/src/types/offers.d.ts
+++ b/apps/portal/src/types/offers.d.ts
@@ -25,7 +25,7 @@ export type Experience = {
id: string;
jobType: JobType?;
level: string?;
- location: string?;
+ location: Location?;
monthlySalary: Valuation?;
title: string?;
totalCompensation: Valuation?;
@@ -79,7 +79,7 @@ export type ProfileOffer = {
company: OffersCompany;
id: string;
jobType: JobType;
- location: string;
+ location: Location;
monthYearReceived: Date;
negotiationStrategy: string;
offersFullTime: FullTime?;
@@ -163,7 +163,7 @@ export type AnalysisHighestOffer = {
company: OffersCompany;
id: string;
level: string;
- location: string;
+ location: Location;
totalYoe: number;
};
@@ -173,7 +173,7 @@ export type AnalysisOffer = {
income: Valuation;
jobType: JobType;
level: string;
- location: string;
+ location: Location;
monthYearReceived: Date;
negotiationStrategy: string;
previousCompanies: Array;
@@ -202,7 +202,17 @@ export type UserProfileOffer = {
income: Valuation;
jobType: JobType;
level: string;
- location: string;
+ location: Location;
monthYearReceived: Date;
title: string;
};
+
+export type Location = {
+ cityId: string;
+ cityName: string;
+ countryCode: string;
+ countryId: string;
+ countryName: string;
+ stateId: string;
+ stateName: string;
+};
From 89644e8c2b2d2cde6d78269552055f205010ce9f Mon Sep 17 00:00:00 2001
From: Stuart Long Chay Boon
Date: Wed, 2 Nov 2022 16:11:06 +0800
Subject: [PATCH 4/8] [offers][feat] integrate cityId into create profile
endpoint
---
.../router/offers/offers-profile-router.ts | 149 +++++++++++++++++-
1 file changed, 144 insertions(+), 5 deletions(-)
diff --git a/apps/portal/src/server/router/offers/offers-profile-router.ts b/apps/portal/src/server/router/offers/offers-profile-router.ts
index 7e4ed3c5..505c6ac9 100644
--- a/apps/portal/src/server/router/offers/offers-profile-router.ts
+++ b/apps/portal/src/server/router/offers/offers-profile-router.ts
@@ -34,12 +34,12 @@ const company = z.object({
});
const offer = z.object({
+ cityId: z.string(),
comments: z.string(),
company: company.nullish(),
companyId: z.string(),
id: z.string().optional(),
jobType: z.string().regex(createValidationRegex(Object.keys(JobType), null)),
- location: z.string(),
monthYearReceived: z.date(),
negotiationStrategy: z.string(),
offersFullTime: z
@@ -74,6 +74,7 @@ const offer = z.object({
const experience = z.object({
backgroundId: z.string().nullish(),
+ cityId: z.string().nullish(),
company: company.nullish(),
companyId: z.string().nullish(),
durationInMonths: z.number().nullish(),
@@ -83,7 +84,6 @@ const experience = z.object({
.regex(createValidationRegex(Object.keys(JobType), null))
.nullish(),
level: z.string().nullish(),
- location: z.string().nullish(),
monthlySalary: valuation.nullish(),
monthlySalaryId: z.string().nullish(),
title: z.string().nullish(),
@@ -375,6 +375,39 @@ export const offersProfileRouter = createRouter()
input.background.experiences.map(async (x) => {
if (x.jobType === JobType.FULLTIME) {
if (x.companyId) {
+ if (x.cityId) {
+ return {
+ company: {
+ connect: {
+ id: x.companyId,
+ },
+ },
+ durationInMonths: x.durationInMonths,
+ jobType: x.jobType,
+ level: x.level,
+ location: {
+ connect: {
+ id: x.cityId
+ }
+ },
+ title: x.title,
+ totalCompensation:
+ x.totalCompensation != null
+ ? {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ x.totalCompensation.value,
+ x.totalCompensation.currency,
+ baseCurrencyString,
+ ),
+ currency: x.totalCompensation.currency,
+ value: x.totalCompensation.value,
+ },
+ }
+ : undefined,
+ };
+ }
return {
company: {
connect: {
@@ -402,11 +435,40 @@ export const offersProfileRouter = createRouter()
: undefined,
};
}
+ if (x.cityId) {
+ return {
+ durationInMonths: x.durationInMonths,
+ jobType: x.jobType,
+ level: x.level,
+ location: {
+ connect: {
+ where: {
+ id: x.cityId
+ }
+ }
+ },
+ title: x.title,
+ totalCompensation:
+ x.totalCompensation != null
+ ? {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ x.totalCompensation.value,
+ x.totalCompensation.currency,
+ baseCurrencyString,
+ ),
+ currency: x.totalCompensation.currency,
+ value: x.totalCompensation.value,
+ },
+ }
+ : undefined,
+ };
+ }
return {
durationInMonths: x.durationInMonths,
jobType: x.jobType,
level: x.level,
- location: x.location,
title: x.title,
totalCompensation:
x.totalCompensation != null
@@ -427,6 +489,40 @@ export const offersProfileRouter = createRouter()
}
if (x.jobType === JobType.INTERN) {
if (x.companyId) {
+ if (x.cityId) {
+ return {
+ company: {
+ connect: {
+ id: x.companyId,
+ },
+ },
+ durationInMonths: x.durationInMonths,
+ jobType: x.jobType,
+ location: {
+ connect: {
+ where: {
+ id: x.cityId
+ }
+ }
+ },
+ monthlySalary:
+ x.monthlySalary != null
+ ? {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ x.monthlySalary.value,
+ x.monthlySalary.currency,
+ baseCurrencyString,
+ ),
+ currency: x.monthlySalary.currency,
+ value: x.monthlySalary.value,
+ },
+ }
+ : undefined,
+ title: x.title,
+ };
+ }
return {
company: {
connect: {
@@ -453,6 +549,37 @@ export const offersProfileRouter = createRouter()
title: x.title,
};
}
+
+ if (x.cityId) {
+ return {
+ durationInMonths: x.durationInMonths,
+ jobType: x.jobType,
+ location: {
+ connect: {
+ where: {
+ id: x.cityId
+ }
+ }
+ },
+ monthlySalary:
+ x.monthlySalary != null
+ ? {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ x.monthlySalary.value,
+ x.monthlySalary.currency,
+ baseCurrencyString,
+ ),
+ currency: x.monthlySalary.currency,
+ value: x.monthlySalary.value,
+ },
+ }
+ : undefined,
+ title: x.title,
+ };
+ }
+
return {
durationInMonths: x.durationInMonths,
jobType: x.jobType,
@@ -513,7 +640,13 @@ export const offersProfileRouter = createRouter()
},
},
jobType: x.jobType,
- location: x.location,
+ location: {
+ connect: {
+ where: {
+ id: x.cityId
+ }
+ }
+ },
monthYearReceived: x.monthYearReceived,
negotiationStrategy: x.negotiationStrategy,
offersIntern: {
@@ -553,7 +686,13 @@ export const offersProfileRouter = createRouter()
},
},
jobType: x.jobType,
- location: x.location,
+ location: {
+ connect: {
+ where: {
+ id: x.cityId
+ }
+ }
+ },
monthYearReceived: x.monthYearReceived,
negotiationStrategy: x.negotiationStrategy,
offersFullTime: {
From bebbebf9dcef480699019512a4311cb7f040b50c Mon Sep 17 00:00:00 2001
From: Stuart Long Chay Boon
Date: Wed, 2 Nov 2022 16:30:08 +0800
Subject: [PATCH 5/8] [offers][feat] integrate location with update profile
endpoint
---
.../router/offers/offers-profile-router.ts | 344 +++++++++++++++---
1 file changed, 298 insertions(+), 46 deletions(-)
diff --git a/apps/portal/src/server/router/offers/offers-profile-router.ts b/apps/portal/src/server/router/offers/offers-profile-router.ts
index 505c6ac9..81f73458 100644
--- a/apps/portal/src/server/router/offers/offers-profile-router.ts
+++ b/apps/portal/src/server/router/offers/offers-profile-router.ts
@@ -1035,35 +1035,110 @@ export const offersProfileRouter = createRouter()
exp.totalCompensation?.currency != null &&
exp.totalCompensation?.value != null
) {
+ // FULLTIME
if (exp.companyId) {
+ if (exp.cityId) {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ level: exp.level,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
+ title: exp.title,
+ totalCompensation: exp.totalCompensation
+ ? {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ exp.totalCompensation.value,
+ exp.totalCompensation.currency,
+ baseCurrencyString,
+ ),
+ currency: exp.totalCompensation.currency,
+ value: exp.totalCompensation.value,
+ },
+ }
+ : undefined,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ } else {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ level: exp.level,
+ title: exp.title,
+ totalCompensation: exp.totalCompensation
+ ? {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ exp.totalCompensation.value,
+ exp.totalCompensation.currency,
+ baseCurrencyString,
+ ),
+ currency: exp.totalCompensation.currency,
+ value: exp.totalCompensation.value,
+ },
+ }
+ : undefined,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ }
+ } else if (exp.cityId) {
await ctx.prisma.offersBackground.update({
data: {
experiences: {
create: {
- company: {
- connect: {
- id: exp.companyId,
- },
- },
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
level: exp.level,
- location: exp.location,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
title: exp.title,
- totalCompensation: exp.totalCompensation
- ? {
- create: {
- baseCurrency: baseCurrencyString,
- baseValue: await convert(
- exp.totalCompensation.value,
- exp.totalCompensation.currency,
- baseCurrencyString,
- ),
- currency: exp.totalCompensation.currency,
- value: exp.totalCompensation.value,
- },
- }
- : undefined,
+ totalCompensation: {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ exp.totalCompensation.value,
+ exp.totalCompensation.currency,
+ baseCurrencyString,
+ ),
+ currency: exp.totalCompensation.currency,
+ value: exp.totalCompensation.value,
+ },
+ },
},
},
},
@@ -1079,7 +1154,6 @@ export const offersProfileRouter = createRouter()
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
level: exp.level,
- location: exp.location,
title: exp.title,
totalCompensation: {
create: {
@@ -1102,19 +1176,67 @@ export const offersProfileRouter = createRouter()
});
}
} else if (exp.companyId) {
+ if (exp.cityId) {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ level: exp.level,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
+ title: exp.title,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ } else {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ level: exp.level,
+ title: exp.title,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ }
+ } else if (exp.cityId) {
await ctx.prisma.offersBackground.update({
data: {
experiences: {
create: {
- company: {
- connect: {
- id: exp.companyId,
- },
- },
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
level: exp.level,
- location: exp.location,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
title: exp.title,
},
},
@@ -1131,7 +1253,6 @@ export const offersProfileRouter = createRouter()
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
level: exp.level,
- location: exp.location,
title: exp.title,
},
},
@@ -1146,19 +1267,90 @@ export const offersProfileRouter = createRouter()
exp.monthlySalary?.currency != null &&
exp.monthlySalary?.value != null
) {
+ // INTERN
if (exp.companyId) {
+ if (exp.cityId) {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
+ monthlySalary: {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ exp.monthlySalary.value,
+ exp.monthlySalary.currency,
+ baseCurrencyString,
+ ),
+ currency: exp.monthlySalary.currency,
+ value: exp.monthlySalary.value,
+ },
+ },
+ title: exp.title,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ } else {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ monthlySalary: {
+ create: {
+ baseCurrency: baseCurrencyString,
+ baseValue: await convert(
+ exp.monthlySalary.value,
+ exp.monthlySalary.currency,
+ baseCurrencyString,
+ ),
+ currency: exp.monthlySalary.currency,
+ value: exp.monthlySalary.value,
+ },
+ },
+ title: exp.title,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ }
+ } else if (exp.cityId) {
await ctx.prisma.offersBackground.update({
data: {
experiences: {
create: {
- company: {
- connect: {
- id: exp.companyId,
- },
- },
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
- location: exp.location,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
monthlySalary: {
create: {
baseCurrency: baseCurrencyString,
@@ -1186,7 +1378,6 @@ export const offersProfileRouter = createRouter()
create: {
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
- location: exp.location,
monthlySalary: {
create: {
baseCurrency: baseCurrencyString,
@@ -1209,18 +1400,64 @@ export const offersProfileRouter = createRouter()
});
}
} else if (exp.companyId) {
+ if (exp.cityId) {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ location: {
+ connect: {
+ id: exp.cityId,
+ }
+ },
+ title: exp.title,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ } else {
+ await ctx.prisma.offersBackground.update({
+ data: {
+ experiences: {
+ create: {
+ company: {
+ connect: {
+ id: exp.companyId,
+ },
+ },
+ durationInMonths: exp.durationInMonths,
+ jobType: exp.jobType,
+ title: exp.title,
+ },
+ },
+ },
+ where: {
+ id: input.background.id,
+ },
+ });
+ }
+ } else if (exp.cityId) {
await ctx.prisma.offersBackground.update({
data: {
experiences: {
create: {
- company: {
- connect: {
- id: exp.companyId,
- },
- },
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
- location: exp.location,
+ location: {
+ connect: {
+ id: exp.cityId
+ }
+ },
title: exp.title,
},
},
@@ -1236,7 +1473,6 @@ export const offersProfileRouter = createRouter()
create: {
durationInMonths: exp.durationInMonths,
jobType: exp.jobType,
- location: exp.location,
title: exp.title,
},
},
@@ -1324,12 +1560,20 @@ export const offersProfileRouter = createRouter()
await ctx.prisma.offersOffer.update({
data: {
comments: offerToUpdate.comments,
- companyId: offerToUpdate.companyId,
+ company: {
+ connect: {
+ id: offerToUpdate.companyId
+ }
+ },
jobType:
offerToUpdate.jobType === JobType.FULLTIME
? JobType.FULLTIME
: JobType.INTERN,
- location: offerToUpdate.location,
+ location: {
+ connect: {
+ id: offerToUpdate.cityId
+ }
+ },
monthYearReceived: offerToUpdate.monthYearReceived,
negotiationStrategy: offerToUpdate.negotiationStrategy,
},
@@ -1466,7 +1710,11 @@ export const offersProfileRouter = createRouter()
},
},
jobType: offerToUpdate.jobType,
- location: offerToUpdate.location,
+ location: {
+ connect: {
+ id: offerToUpdate.cityId
+ }
+ },
monthYearReceived: offerToUpdate.monthYearReceived,
negotiationStrategy: offerToUpdate.negotiationStrategy,
offersIntern: {
@@ -1520,7 +1768,11 @@ export const offersProfileRouter = createRouter()
},
},
jobType: offerToUpdate.jobType,
- location: offerToUpdate.location,
+ location: {
+ connect: {
+ id: offerToUpdate.cityId
+ }
+ },
monthYearReceived: offerToUpdate.monthYearReceived,
negotiationStrategy: offerToUpdate.negotiationStrategy,
offersFullTime: {
From ac2d047d942613a69bc2d8fbbb98d4a00fc8b172 Mon Sep 17 00:00:00 2001
From: Zhang Ziqing
Date: Wed, 2 Nov 2022 17:22:46 +0800
Subject: [PATCH 6/8] [offers][feat] integrate location for offer table and
profile
---
.../offers/dashboard/DashboardOfferCard.tsx | 2 +-
.../components/offers/profile/OfferCard.tsx | 8 +++---
.../components/offers/table/OffersTable.tsx | 9 ++++---
apps/portal/src/components/offers/types.ts | 6 +++--
apps/portal/src/pages/offers/index.tsx | 26 ++++++++++++++++++-
5 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx b/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx
index df49ada9..748a4142 100644
--- a/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx
+++ b/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx
@@ -36,7 +36,7 @@ export default function DashboardProfileCard({
{location
- ? `Company: ${company.name}, ${location}`
+ ? `Company: ${company.name}, ${location.cityName}`
: `Company: ${company.name}`}
{level && Level: {level}
}
diff --git a/apps/portal/src/components/offers/profile/OfferCard.tsx b/apps/portal/src/components/offers/profile/OfferCard.tsx
index 6d02f134..0fcc9823 100644
--- a/apps/portal/src/components/offers/profile/OfferCard.tsx
+++ b/apps/portal/src/components/offers/profile/OfferCard.tsx
@@ -40,7 +40,7 @@ export default function OfferCard({
- {location ? `${companyName}, ${location}` : companyName}
+ {location ? `${companyName}, ${location.cityName}` : companyName}
@@ -92,11 +92,11 @@ export default function OfferCard({
)}
- {totalCompensation && (
+ {(base || stocks || bonus) && totalCompensation && (
- Base / year: {base} ⋅ Stocks / year: {stocks} ⋅ Bonus / year:{' '}
- {bonus}
+ Base / year: {base ?? 'N/A'} ⋅ Stocks / year:{' '}
+ {stocks ?? 'N/A'} ⋅ Bonus / year: {bonus ?? 'N/A'}
)}
diff --git a/apps/portal/src/components/offers/table/OffersTable.tsx b/apps/portal/src/components/offers/table/OffersTable.tsx
index 627cb330..9a400b76 100644
--- a/apps/portal/src/components/offers/table/OffersTable.tsx
+++ b/apps/portal/src/components/offers/table/OffersTable.tsx
@@ -21,10 +21,12 @@ import type { DashboardOffer, GetOffersResponse, Paging } from '~/types/offers';
const NUMBER_OF_OFFERS_IN_PAGE = 10;
export type OffersTableProps = Readonly<{
+ cityFilter: string;
companyFilter: string;
jobTitleFilter: string;
}>;
export default function OffersTable({
+ cityFilter,
companyFilter,
jobTitleFilter,
}: OffersTableProps) {
@@ -53,10 +55,11 @@ export default function OffersTable({
[
'offers.list',
{
+ // Location: 'Singapore, Singapore', // TODO: Geolocation
+ cityId: cityFilter,
companyId: companyFilter,
currency,
limit: NUMBER_OF_OFFERS_IN_PAGE,
- location: 'Singapore, Singapore', // TODO: Geolocation
offset: pagination.currentPage,
sortBy: OfferTableSortBy[selectedFilter] ?? '-monthYearReceived',
title: jobTitleFilter,
@@ -102,8 +105,8 @@ export default function OffersTable({
))}
-
-
View all offers in
+
+
Display offers in
setCurrency(value)}
selectedCurrency={currency}
diff --git a/apps/portal/src/components/offers/types.ts b/apps/portal/src/components/offers/types.ts
index 366ca25b..1ee07a15 100644
--- a/apps/portal/src/components/offers/types.ts
+++ b/apps/portal/src/components/offers/types.ts
@@ -2,6 +2,8 @@ import type { JobType } from '@prisma/client';
import type { MonthYear } from '~/components/shared/MonthYearPicker';
+import type { Location } from '~/types/offers';
+
export const HOME_URL = '/offers';
/*
@@ -50,7 +52,7 @@ type ExperiencePostData = {
id?: string;
jobType?: string | null;
level?: string | null;
- location?: string | null;
+ location?: Location | null;
monthlySalary?: Money | null;
title?: string | null;
totalCompensation?: Money | null;
@@ -132,7 +134,7 @@ export type OfferDisplayData = {
jobLevel?: string | null;
jobTitle?: string | null;
jobType?: JobType;
- location?: string | null;
+ location?: Location | null;
monthlySalary?: string | null;
negotiationStrategy?: string | null;
otherComment?: string | null;
diff --git a/apps/portal/src/pages/offers/index.tsx b/apps/portal/src/pages/offers/index.tsx
index e696ca10..07bd3f8c 100644
--- a/apps/portal/src/pages/offers/index.tsx
+++ b/apps/portal/src/pages/offers/index.tsx
@@ -1,5 +1,6 @@
import Link from 'next/link';
import { useState } from 'react';
+import { MapPinIcon } from '@heroicons/react/24/outline';
import { Banner } from '@tih/ui';
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
@@ -7,9 +8,12 @@ import OffersTable from '~/components/offers/table/OffersTable';
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
+import CitiesTypeahead from '../../components/shared/CitiesTypeahead';
+
export default function OffersHomePage() {
const [jobTitleFilter, setjobTitleFilter] = useState('software-engineer');
const [companyFilter, setCompanyFilter] = useState('');
+ const [cityFilter, setCityFilter] = useState('');
const { event: gaEvent } = useGoogleAnalytics();
return (
@@ -21,6 +25,25 @@ export default function OffersHomePage() {
. ⭐
+
+
+
+
+ {
+ if (option) {
+ setCityFilter(option.value);
+ gaEvent({
+ action: `offers.table_filter_city_${option.value}`,
+ category: 'engagement',
+ label: 'Filter by city',
+ });
+ }
+ }}
+ />
+
@@ -58,7 +81,7 @@ export default function OffersHomePage() {
if (option) {
setCompanyFilter(option.value);
gaEvent({
- action: 'offers.table_filter_company',
+ action: `offers.table_filter_company_${option.value}`,
category: 'engagement',
label: 'Filter by company',
});
@@ -70,6 +93,7 @@ export default function OffersHomePage() {
From d6d25df35b0f453319a32b8fea59127ca29814c2 Mon Sep 17 00:00:00 2001
From: Zhang Ziqing
Date: Wed, 2 Nov 2022 18:01:04 +0800
Subject: [PATCH 7/8] [offers][chore] fix import of cities typeahead
---
apps/portal/src/pages/offers/index.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/apps/portal/src/pages/offers/index.tsx b/apps/portal/src/pages/offers/index.tsx
index 07bd3f8c..ad0ff41c 100644
--- a/apps/portal/src/pages/offers/index.tsx
+++ b/apps/portal/src/pages/offers/index.tsx
@@ -5,11 +5,10 @@ import { Banner } from '@tih/ui';
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
import OffersTable from '~/components/offers/table/OffersTable';
+import CitiesTypeahead from '~/components/shared/CitiesTypeahead';
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
-import CitiesTypeahead from '../../components/shared/CitiesTypeahead';
-
export default function OffersHomePage() {
const [jobTitleFilter, setjobTitleFilter] = useState('software-engineer');
const [companyFilter, setCompanyFilter] = useState('');
From a31230f7c30a004c34f165390401934af35c681f Mon Sep 17 00:00:00 2001
From: Ai Ling
Date: Wed, 2 Nov 2022 19:55:08 +0800
Subject: [PATCH 8/8] [offers][feat] Use city typeahead for location field
---
.../portal/src/components/offers/constants.ts | 15 ----
.../offersSubmission/OffersSubmissionForm.tsx | 4 +-
.../submissionForm/BackgroundForm.tsx | 53 ++++++++---
.../submissionForm/OfferDetailsForm.tsx | 90 ++++++++++++-------
apps/portal/src/components/offers/types.ts | 6 +-
.../offers/profile/edit/[offerProfileId].tsx | 6 +-
6 files changed, 110 insertions(+), 64 deletions(-)
diff --git a/apps/portal/src/components/offers/constants.ts b/apps/portal/src/components/offers/constants.ts
index e2b14d96..d49dca1a 100644
--- a/apps/portal/src/components/offers/constants.ts
+++ b/apps/portal/src/components/offers/constants.ts
@@ -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',
diff --git a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx
index 325c9afc..98e9146a 100644
--- a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx
+++ b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx
@@ -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(),
@@ -277,7 +277,7 @@ export default function OffersSubmissionForm({
-
- {
- if (option) {
- setValue(`offers.${index}.companyId`, option.value);
- setValue(`offers.${index}.companyName`, option.label);
- }
- }}
- />
-
-
{
+ if (option) {
+ setValue(`offers.${index}.companyId`, option.value);
+ setValue(`offers.${index}.companyName`, option.label);
+ }
+ }}
+ />
+ {
+ if (option) {
+ setValue(`offers.${index}.cityId`, option.value);
+ setValue(`offers.${index}.cityName`, option.label);
+ } else {
+ setValue(`offers.${index}.cityId`, '');
+ setValue(`offers.${index}.cityName`, '');
+ }
+ }}
/>
@@ -305,6 +316,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 (
@@ -342,16 +359,23 @@ function InternshipOfferDetailsForm({
}}
/>
-
{
+ if (option) {
+ setValue(`offers.${index}.cityId`, option.value);
+ setValue(`offers.${index}.cityName`, option.label);
+ } else {
+ setValue(`offers.${index}.cityId`, '');
+ setValue(`offers.${index}.cityName`, '');
+ }
+ }}
/>
diff --git a/apps/portal/src/components/offers/types.ts b/apps/portal/src/components/offers/types.ts
index 1ee07a15..0e963a17 100644
--- a/apps/portal/src/components/offers/types.ts
+++ b/apps/portal/src/components/offers/types.ts
@@ -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;
diff --git a/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx b/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx
index 05e47b7c..829acb28 100644
--- a/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx
+++ b/apps/portal/src/pages/offers/profile/edit/[offerProfileId].tsx
@@ -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,