mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-28 12:43:12 +08:00
[offers][feat] add get user profile endpoint
This commit is contained in:
@ -33,8 +33,9 @@ import type {
|
|||||||
ProfileAnalysis,
|
ProfileAnalysis,
|
||||||
ProfileOffer,
|
ProfileOffer,
|
||||||
SpecificYoe,
|
SpecificYoe,
|
||||||
Valuation,
|
UserProfile,
|
||||||
} from '~/types/offers';
|
UserProfileOffer,
|
||||||
|
Valuation} from '~/types/offers';
|
||||||
|
|
||||||
const analysisOfferDtoMapper = (
|
const analysisOfferDtoMapper = (
|
||||||
offer: OffersOffer & {
|
offer: OffersOffer & {
|
||||||
@ -626,3 +627,84 @@ export const getOffersResponseMapper = (
|
|||||||
};
|
};
|
||||||
return getOffersResponse;
|
return getOffersResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getUserProfileResponeMapper = (res: User & {
|
||||||
|
OffersProfile: Array<OffersProfile & {
|
||||||
|
offers: Array<OffersOffer & {
|
||||||
|
company: Company;
|
||||||
|
offersFullTime: (OffersFullTime & { totalCompensation: OffersCurrency }) | null;
|
||||||
|
offersIntern: (OffersIntern & { monthlySalary: OffersCurrency }) | null;
|
||||||
|
}>;
|
||||||
|
}>;
|
||||||
|
} | null): Array<UserProfile> => {
|
||||||
|
if (res) {
|
||||||
|
return res.OffersProfile.map((profile) => {
|
||||||
|
return {
|
||||||
|
createdAt: profile.createdAt,
|
||||||
|
id: profile.id,
|
||||||
|
offers: profile.offers.map((offer) => {
|
||||||
|
return userProfileOfferDtoMapper(offer)
|
||||||
|
}),
|
||||||
|
profileName: profile.profileName,
|
||||||
|
token: profile.editToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const userProfileOfferDtoMapper = (
|
||||||
|
offer: OffersOffer & {
|
||||||
|
company: Company;
|
||||||
|
offersFullTime: (OffersFullTime & { totalCompensation: OffersCurrency }) | null;
|
||||||
|
offersIntern: (OffersIntern & { monthlySalary: OffersCurrency }) | null;
|
||||||
|
}): UserProfileOffer => {
|
||||||
|
const mappedOffer: UserProfileOffer = {
|
||||||
|
company: offersCompanyDtoMapper(offer.company),
|
||||||
|
id: offer.id,
|
||||||
|
income: {
|
||||||
|
baseCurrency: '',
|
||||||
|
baseValue: -1,
|
||||||
|
currency: '',
|
||||||
|
id: '',
|
||||||
|
value: -1,
|
||||||
|
},
|
||||||
|
jobType: offer.jobType,
|
||||||
|
level: offer.offersFullTime?.level ?? '',
|
||||||
|
location: offer.location,
|
||||||
|
monthYearReceived: offer.monthYearReceived,
|
||||||
|
title:
|
||||||
|
offer.jobType === JobType.FULLTIME
|
||||||
|
? offer.offersFullTime?.title ?? ''
|
||||||
|
: offer.offersIntern?.title ?? '',
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offer.offersFullTime?.totalCompensation) {
|
||||||
|
mappedOffer.income.value =
|
||||||
|
offer.offersFullTime.totalCompensation.value;
|
||||||
|
mappedOffer.income.currency =
|
||||||
|
offer.offersFullTime.totalCompensation.currency;
|
||||||
|
mappedOffer.income.id = offer.offersFullTime.totalCompensation.id;
|
||||||
|
mappedOffer.income.baseValue =
|
||||||
|
offer.offersFullTime.totalCompensation.baseValue;
|
||||||
|
mappedOffer.income.baseCurrency =
|
||||||
|
offer.offersFullTime.totalCompensation.baseCurrency;
|
||||||
|
} else if (offer.offersIntern?.monthlySalary) {
|
||||||
|
mappedOffer.income.value = offer.offersIntern.monthlySalary.value;
|
||||||
|
mappedOffer.income.currency =
|
||||||
|
offer.offersIntern.monthlySalary.currency;
|
||||||
|
mappedOffer.income.id = offer.offersIntern.monthlySalary.id;
|
||||||
|
mappedOffer.income.baseValue =
|
||||||
|
offer.offersIntern.monthlySalary.baseValue;
|
||||||
|
mappedOffer.income.baseCurrency =
|
||||||
|
offer.offersIntern.monthlySalary.baseCurrency;
|
||||||
|
} else {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'NOT_FOUND',
|
||||||
|
message: 'Total Compensation or Salary not found',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappedOffer
|
||||||
|
}
|
@ -2,7 +2,7 @@ import { z } from 'zod';
|
|||||||
import * as trpc from '@trpc/server';
|
import * as trpc from '@trpc/server';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
addToProfileResponseMapper,
|
addToProfileResponseMapper, getUserProfileResponeMapper,
|
||||||
} from '~/mappers/offers-mappers';
|
} from '~/mappers/offers-mappers';
|
||||||
|
|
||||||
import { createProtectedRouter } from '../context';
|
import { createProtectedRouter } from '../context';
|
||||||
@ -13,35 +13,68 @@ export const offersUserProfileRouter = createProtectedRouter()
|
|||||||
token: z.string(),
|
token: z.string(),
|
||||||
}),
|
}),
|
||||||
async resolve({ ctx, input }) {
|
async resolve({ ctx, input }) {
|
||||||
const profile = await ctx.prisma.offersProfile.findFirst({
|
const profile = await ctx.prisma.offersProfile.findFirst({
|
||||||
where: {
|
where: {
|
||||||
id: input.profileId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const profileEditToken = profile?.editToken;
|
|
||||||
if (profileEditToken === input.token) {
|
|
||||||
|
|
||||||
const userId = ctx.session.user.id
|
|
||||||
const updated = await ctx.prisma.offersProfile.update({
|
|
||||||
data: {
|
|
||||||
user: {
|
|
||||||
connect: {
|
|
||||||
id: userId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
where: {
|
|
||||||
id: input.profileId,
|
id: input.profileId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return addToProfileResponseMapper(updated);
|
const profileEditToken = profile?.editToken;
|
||||||
}
|
if (profileEditToken === input.token) {
|
||||||
|
|
||||||
throw new trpc.TRPCError({
|
const userId = ctx.session.user.id
|
||||||
code: 'UNAUTHORIZED',
|
const updated = await ctx.prisma.offersProfile.update({
|
||||||
message: 'Invalid token.',
|
data: {
|
||||||
});
|
user: {
|
||||||
|
connect: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: input.profileId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return addToProfileResponseMapper(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new trpc.TRPCError({
|
||||||
|
code: 'UNAUTHORIZED',
|
||||||
|
message: 'Invalid token.',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
.mutation('getUserProfiles', {
|
||||||
|
async resolve({ ctx }) {
|
||||||
|
const userId = ctx.session.user.id
|
||||||
|
const result = await ctx.prisma.user.findFirst({
|
||||||
|
include: {
|
||||||
|
OffersProfile: {
|
||||||
|
include: {
|
||||||
|
offers: {
|
||||||
|
include: {
|
||||||
|
company: true,
|
||||||
|
offersFullTime: {
|
||||||
|
include: {
|
||||||
|
totalCompensation: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
offersIntern: {
|
||||||
|
include: {
|
||||||
|
monthlySalary: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: userId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return getUserProfileResponeMapper(result)
|
||||||
|
}
|
||||||
});
|
});
|
19
apps/portal/src/types/offers.d.ts
vendored
19
apps/portal/src/types/offers.d.ts
vendored
@ -183,3 +183,22 @@ export type AddToProfileResponse = {
|
|||||||
profileName: string;
|
profileName: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UserProfile = {
|
||||||
|
createdAt: Date;
|
||||||
|
id: string;
|
||||||
|
offers: Array<UserProfileOffers>;
|
||||||
|
profileName: string;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserProfileOffer = {
|
||||||
|
company: OffersCompany;
|
||||||
|
id: string;
|
||||||
|
income: Valuation;
|
||||||
|
jobType: JobType;
|
||||||
|
level: string;
|
||||||
|
location: string;
|
||||||
|
monthYearReceived: Date;
|
||||||
|
title: string;
|
||||||
|
}
|
Reference in New Issue
Block a user