mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-28 04:33:42 +08:00
[offers][refactor] Refactor the sorting to use prisma's WHERE api
This commit is contained in:
@ -9,13 +9,13 @@ import {
|
|||||||
YOE_CATEGORY,
|
YOE_CATEGORY,
|
||||||
} from '~/components/offers/table/types';
|
} from '~/components/offers/table/types';
|
||||||
|
|
||||||
|
import { Currency } from '~/utils/offers/currency/CurrencyEnum';
|
||||||
import CurrencySelector from '~/utils/offers/currency/CurrencySelector';
|
import CurrencySelector from '~/utils/offers/currency/CurrencySelector';
|
||||||
import { trpc } from '~/utils/trpc';
|
import { trpc } from '~/utils/trpc';
|
||||||
|
|
||||||
import OffersRow from './OffersRow';
|
import OffersRow from './OffersRow';
|
||||||
|
|
||||||
import type { DashboardOffer, GetOffersResponse, Paging } from '~/types/offers';
|
import type { DashboardOffer, GetOffersResponse, Paging } from '~/types/offers';
|
||||||
import { Currency } from '~/utils/offers/currency/CurrencyEnum';
|
|
||||||
|
|
||||||
const NUMBER_OF_OFFERS_IN_PAGE = 10;
|
const NUMBER_OF_OFFERS_IN_PAGE = 10;
|
||||||
export type OffersTableProps = Readonly<{
|
export type OffersTableProps = Readonly<{
|
||||||
|
@ -6,12 +6,11 @@ function Test() {
|
|||||||
const data = trpc.useQuery([
|
const data = trpc.useQuery([
|
||||||
'offers.list',
|
'offers.list',
|
||||||
{
|
{
|
||||||
currency: "aed",
|
|
||||||
limit: 100,
|
limit: 100,
|
||||||
location: 'Singapore, Singapore',
|
location: 'Singapore, Singapore',
|
||||||
offset: 0,
|
offset: 0,
|
||||||
sortBy: '+totalCompensation',
|
sortBy: '+totalCompensation',
|
||||||
yoeCategory: 2,
|
yoeCategory: 1,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import { TRPCError } from "@trpc/server";
|
import { z } from 'zod';
|
||||||
import { z } from "zod";
|
import { TRPCError } from '@trpc/server';
|
||||||
import { dashboardOfferDtoMapper, getOffersResponseMapper } from "~/mappers/offers-mappers";
|
|
||||||
import { convert } from "~/utils/offers/currency/currency-exchange";
|
import {
|
||||||
import { Currency } from "~/utils/offers/currency/CurrencyEnum";
|
dashboardOfferDtoMapper,
|
||||||
import { createRouter } from "../context";
|
getOffersResponseMapper,
|
||||||
|
} from '~/mappers/offers-mappers';
|
||||||
|
import { convert } from '~/utils/offers/currency/currency-exchange';
|
||||||
|
import { Currency } from '~/utils/offers/currency/CurrencyEnum';
|
||||||
|
|
||||||
|
import { createRouter } from '../context';
|
||||||
|
|
||||||
const yoeCategoryMap: Record<number, string> = {
|
const yoeCategoryMap: Record<number, string> = {
|
||||||
0: 'Internship',
|
0: 'Internship',
|
||||||
@ -84,18 +89,49 @@ export const offersRouter = createRouter().query('list', {
|
|||||||
where: {
|
where: {
|
||||||
AND: [
|
AND: [
|
||||||
{
|
{
|
||||||
location: input.location,
|
location:
|
||||||
|
input.location.length === 0 ? undefined : input.location,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offersIntern: {
|
offersIntern: {
|
||||||
isNot: null,
|
isNot: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
offersIntern: {
|
||||||
|
title:
|
||||||
|
input.title && input.title.length !== 0
|
||||||
|
? input.title
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offersIntern: {
|
||||||
|
monthlySalary: {
|
||||||
|
value: {
|
||||||
|
gte: input.salaryMin ?? undefined,
|
||||||
|
lte: input.salaryMax ?? undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
offersFullTime: {
|
offersFullTime: {
|
||||||
is: null,
|
is: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
companyId:
|
||||||
|
input.companyId && input.companyId.length !== 0
|
||||||
|
? input.companyId
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
monthYearReceived: {
|
||||||
|
gte: input.dateStart ?? undefined,
|
||||||
|
lte: input.dateEnd ?? undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -128,7 +164,8 @@ export const offersRouter = createRouter().query('list', {
|
|||||||
where: {
|
where: {
|
||||||
AND: [
|
AND: [
|
||||||
{
|
{
|
||||||
location: input.location,
|
location:
|
||||||
|
input.location.length === 0 ? undefined : input.location,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offersIntern: {
|
offersIntern: {
|
||||||
@ -140,6 +177,30 @@ export const offersRouter = createRouter().query('list', {
|
|||||||
isNot: null,
|
isNot: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
offersFullTime: {
|
||||||
|
title:
|
||||||
|
input.title && input.title.length !== 0
|
||||||
|
? input.title
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offersFullTime: {
|
||||||
|
totalCompensation: {
|
||||||
|
value: {
|
||||||
|
gte: input.salaryMin ?? undefined,
|
||||||
|
lte: input.salaryMax ?? undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
companyId:
|
||||||
|
input.companyId && input.companyId.length !== 0
|
||||||
|
? input.companyId
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
profile: {
|
profile: {
|
||||||
background: {
|
background: {
|
||||||
@ -150,27 +211,52 @@ export const offersRouter = createRouter().query('list', {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
monthYearReceived: {
|
||||||
|
gte: input.dateStart ?? undefined,
|
||||||
|
lte: input.dateEnd ?? undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// CONVERTING
|
// CONVERTING
|
||||||
const currency = input.currency?.toUpperCase()
|
const currency = input.currency?.toUpperCase();
|
||||||
if (currency != null && currency in Currency) {
|
if (currency != null && currency in Currency) {
|
||||||
data = await Promise.all(
|
data = await Promise.all(
|
||||||
data.map(async (offer) => {
|
data.map(async (offer) => {
|
||||||
|
|
||||||
if (offer.offersFullTime?.totalCompensation) {
|
if (offer.offersFullTime?.totalCompensation) {
|
||||||
offer.offersFullTime.totalCompensation.value = await convert(offer.offersFullTime.totalCompensation.value, offer.offersFullTime.totalCompensation.currency, currency);
|
offer.offersFullTime.totalCompensation.value = await convert(
|
||||||
|
offer.offersFullTime.totalCompensation.value,
|
||||||
|
offer.offersFullTime.totalCompensation.currency,
|
||||||
|
currency,
|
||||||
|
);
|
||||||
offer.offersFullTime.totalCompensation.currency = currency;
|
offer.offersFullTime.totalCompensation.currency = currency;
|
||||||
offer.offersFullTime.baseSalary.value = await convert(offer.offersFullTime.totalCompensation.value, offer.offersFullTime.totalCompensation.currency, currency);
|
offer.offersFullTime.baseSalary.value = await convert(
|
||||||
|
offer.offersFullTime.totalCompensation.value,
|
||||||
|
offer.offersFullTime.totalCompensation.currency,
|
||||||
|
currency,
|
||||||
|
);
|
||||||
offer.offersFullTime.baseSalary.currency = currency;
|
offer.offersFullTime.baseSalary.currency = currency;
|
||||||
offer.offersFullTime.stocks.value = await convert(offer.offersFullTime.totalCompensation.value, offer.offersFullTime.totalCompensation.currency, currency);
|
offer.offersFullTime.stocks.value = await convert(
|
||||||
|
offer.offersFullTime.totalCompensation.value,
|
||||||
|
offer.offersFullTime.totalCompensation.currency,
|
||||||
|
currency,
|
||||||
|
);
|
||||||
offer.offersFullTime.stocks.currency = currency;
|
offer.offersFullTime.stocks.currency = currency;
|
||||||
offer.offersFullTime.bonus.value = await convert(offer.offersFullTime.totalCompensation.value, offer.offersFullTime.totalCompensation.currency, currency);
|
offer.offersFullTime.bonus.value = await convert(
|
||||||
|
offer.offersFullTime.totalCompensation.value,
|
||||||
|
offer.offersFullTime.totalCompensation.currency,
|
||||||
|
currency,
|
||||||
|
);
|
||||||
offer.offersFullTime.bonus.currency = currency;
|
offer.offersFullTime.bonus.currency = currency;
|
||||||
} else if (offer.offersIntern?.monthlySalary) {
|
} else if (offer.offersIntern?.monthlySalary) {
|
||||||
offer.offersIntern.monthlySalary.value = await convert(offer.offersIntern.monthlySalary.value, offer.offersIntern.monthlySalary.currency, currency);
|
offer.offersIntern.monthlySalary.value = await convert(
|
||||||
|
offer.offersIntern.monthlySalary.value,
|
||||||
|
offer.offersIntern.monthlySalary.currency,
|
||||||
|
currency,
|
||||||
|
);
|
||||||
offer.offersIntern.monthlySalary.currency = currency;
|
offer.offersIntern.monthlySalary.currency = currency;
|
||||||
} else {
|
} else {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -184,56 +270,6 @@ export const offersRouter = createRouter().query('list', {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILTERING
|
|
||||||
data = data.filter((offer) => {
|
|
||||||
let validRecord = true;
|
|
||||||
|
|
||||||
if (input.companyId && input.companyId.length !== 0) {
|
|
||||||
validRecord = validRecord && offer.company.id === input.companyId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.title && input.title.length !== 0) {
|
|
||||||
validRecord =
|
|
||||||
validRecord &&
|
|
||||||
(offer.offersFullTime?.title === input.title ||
|
|
||||||
offer.offersIntern?.title === input.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
input.dateStart &&
|
|
||||||
input.dateEnd &&
|
|
||||||
input.dateStart.getTime() <= input.dateEnd.getTime()
|
|
||||||
) {
|
|
||||||
validRecord =
|
|
||||||
validRecord &&
|
|
||||||
offer.monthYearReceived.getTime() >= input.dateStart.getTime() &&
|
|
||||||
offer.monthYearReceived.getTime() <= input.dateEnd.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.salaryMin != null || input.salaryMax != null) {
|
|
||||||
const salary = offer.offersFullTime?.totalCompensation.value
|
|
||||||
? offer.offersFullTime?.totalCompensation.value
|
|
||||||
: offer.offersIntern?.monthlySalary.value;
|
|
||||||
|
|
||||||
if (salary == null) {
|
|
||||||
throw new TRPCError({
|
|
||||||
code: 'NOT_FOUND',
|
|
||||||
message: 'Total Compensation or Salary not found',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.salaryMin != null) {
|
|
||||||
validRecord = validRecord && salary >= input.salaryMin;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.salaryMax != null) {
|
|
||||||
validRecord = validRecord && salary <= input.salaryMax;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return validRecord;
|
|
||||||
});
|
|
||||||
|
|
||||||
// SORTING
|
// SORTING
|
||||||
data = data.sort((offer1, offer2) => {
|
data = data.sort((offer1, offer2) => {
|
||||||
const defaultReturn =
|
const defaultReturn =
|
||||||
|
Reference in New Issue
Block a user