[offers][feat] Add delete OfferProfile API

pull/358/head
BryannYeap 2 years ago
parent 77ad895098
commit d5edb6da60

@ -201,7 +201,7 @@ model OffersBackground {
educations OffersEducation[] // For extensibility in the future educations OffersEducation[] // For extensibility in the future
profile OffersProfile @relation(fields: [offersProfileId], references: [id]) profile OffersProfile @relation(fields: [offersProfileId], references: [id], onDelete: Cascade)
offersProfileId String @unique offersProfileId String @unique
} }
@ -211,7 +211,7 @@ model OffersSpecificYoe {
yoe Int yoe Int
domain String domain String
background OffersBackground @relation(fields: [backgroundId], references: [id]) background OffersBackground @relation(fields: [backgroundId], references: [id], onDelete: Cascade)
backgroundId String backgroundId String
} }
@ -237,7 +237,7 @@ model OffersExperience {
monthlySalary OffersCurrency? @relation("ExperienceMonthlySalary", fields: [monthlySalaryId], references: [id]) monthlySalary OffersCurrency? @relation("ExperienceMonthlySalary", fields: [monthlySalaryId], references: [id])
monthlySalaryId String? @unique monthlySalaryId String? @unique
background OffersBackground @relation(fields: [backgroundId], references: [id]) background OffersBackground @relation(fields: [backgroundId], references: [id], onDelete: Cascade)
backgroundId String backgroundId String
} }
@ -270,12 +270,11 @@ model OffersEducation {
type String? type String?
field String? field String?
// Add more fields
school String? school String?
startDate DateTime? startDate DateTime?
endDate DateTime? endDate DateTime?
background OffersBackground @relation(fields: [backgroundId], references: [id]) background OffersBackground @relation(fields: [backgroundId], references: [id], onDelete: Cascade)
backgroundId String backgroundId String
} }
@ -289,14 +288,14 @@ model OffersReply {
replyingTo OffersReply? @relation("ReplyThread", fields: [replyingToId], references: [id]) replyingTo OffersReply? @relation("ReplyThread", fields: [replyingToId], references: [id])
replies OffersReply[] @relation("ReplyThread") replies OffersReply[] @relation("ReplyThread")
profile OffersProfile @relation(fields: [profileId], references: [id]) profile OffersProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
profileId String profileId String
} }
model OffersOffer { model OffersOffer {
id String @id @default(cuid()) id String @id @default(cuid())
profile OffersProfile @relation(fields: [profileId], references: [id]) profile OffersProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
profileId String profileId String
company Company @relation(fields: [companyId], references: [id]) company Company @relation(fields: [companyId], references: [id])
@ -309,10 +308,10 @@ model OffersOffer {
jobType JobType jobType JobType
OffersIntern OffersIntern? @relation(fields: [offersInternId], references: [id]) OffersIntern OffersIntern? @relation(fields: [offersInternId], references: [id], onDelete: Cascade)
offersInternId String? @unique offersInternId String? @unique
OffersFullTime OffersFullTime? @relation(fields: [offersFullTimeId], references: [id]) OffersFullTime OffersFullTime? @relation(fields: [offersFullTimeId], references: [id], onDelete: Cascade)
offersFullTimeId String? @unique offersFullTimeId String? @unique
} }
@ -323,7 +322,7 @@ model OffersIntern {
specialization String specialization String
internshipCycle String internshipCycle String
startYear Int startYear Int
monthlySalary OffersCurrency @relation(fields: [monthlySalaryId], references: [id]) monthlySalary OffersCurrency @relation(fields: [monthlySalaryId], references: [id], onDelete: Cascade)
monthlySalaryId String @unique monthlySalaryId String @unique
OffersOffer OffersOffer? OffersOffer OffersOffer?
@ -334,13 +333,13 @@ model OffersFullTime {
title String title String
specialization String specialization String
level String level String
totalCompensation OffersCurrency @relation("OfferTotalCompensation", fields: [totalCompensationId], references: [id]) totalCompensation OffersCurrency @relation("OfferTotalCompensation", fields: [totalCompensationId], references: [id], onDelete: Cascade)
totalCompensationId String @unique totalCompensationId String @unique
baseSalary OffersCurrency @relation("OfferBaseSalary", fields: [baseSalaryId], references: [id]) baseSalary OffersCurrency @relation("OfferBaseSalary", fields: [baseSalaryId], references: [id], onDelete: Cascade)
baseSalaryId String @unique baseSalaryId String @unique
bonus OffersCurrency @relation("OfferBonus", fields: [bonusId], references: [id]) bonus OffersCurrency @relation("OfferBonus", fields: [bonusId], references: [id], onDelete: Cascade)
bonusId String @unique bonusId String @unique
stocks OffersCurrency @relation("OfferStocks", fields: [stocksId], references: [id]) stocks OffersCurrency @relation("OfferStocks", fields: [stocksId], references: [id], onDelete: Cascade)
stocksId String @unique stocksId String @unique
OffersOffer OffersOffer? OffersOffer OffersOffer?

@ -14,7 +14,39 @@ function Test() {
}, },
]); ]);
return <>{JSON.stringify(data.data)}</>; const deleteMutation = trpc.useMutation(['offers.profile.delete']);
const handleDelete = (id: string) => {
deleteMutation.mutate({ id });
};
return (
<ul>
<li>
<b>{JSON.stringify(data.data?.paging)}</b>
</li>
<li>
<ul>
{data.data?.data.map((offer) => {
return (
<li key={offer.id}>
<button
className="text-danger-600"
type="button"
onClick={() => {
handleDelete(offer.profileId);
}}>
DELETE THIS PROFILE AND ALL ITS OFFERS
</button>
<div>{JSON.stringify(offer)}</div>
<br />
</li>
);
})}
</ul>
</li>
</ul>
);
} }
export default Test; export default Test;

@ -3,136 +3,142 @@ import React, { useState } from 'react';
import { trpc } from '~/utils/trpc'; import { trpc } from '~/utils/trpc';
function Test() { function Test() {
// F const data = trpc.useQuery([ // F const data = trpc.useQuery([
// 'offers.profile.', // 'offers.profile.',
// { // {
// limit: 3, // limit: 3,
// location: 'Singapore, Singapore', // location: 'Singapore, Singapore',
// offset: 0, // offset: 0,
// yoeCategory: 0, // yoeCategory: 0,
// }, // },
// ]); // ]);
const [createdData, setCreatedData] = useState("") const [createdData, setCreatedData] = useState('');
const createMutation = trpc.useMutation(['offers.profile.create'], { const createMutation = trpc.useMutation(['offers.profile.create'], {
onError(error: any) { onError(error: any) {
alert(error) alert(error);
}, },
onSuccess(data) { onSuccess(data) {
setCreatedData(JSON.stringify(data)) setCreatedData(JSON.stringify(data));
}, },
}); });
const handleClick = () => { const handleClick = () => {
createMutation.mutate({ createMutation.mutate({
"background": { background: {
"educations": [ educations: [
{ {
"endDate": new Date("2018-09-30T07:58:54.000Z"), endDate: new Date('2018-09-30T07:58:54.000Z'),
"field": "Computer Science", field: 'Computer Science',
"school": "National University of Singapore", school: 'National University of Singapore',
"startDate": new Date("2014-09-30T07:58:54.000Z"), startDate: new Date('2014-09-30T07:58:54.000Z'),
"type": "Bachelors" type: 'Bachelors',
} },
], ],
"experiences": [ experiences: [
{ {
"companyId": "cl92szctf0008i9nfxk54bhxn", companyId: 'cl93m87pl0000tx1ofbafqz6f',
"durationInMonths": 24, durationInMonths: 24,
"jobType": "FULLTIME", jobType: 'FULLTIME',
"level": "Junior", level: 'Junior',
// "monthlySalary": undefined, // "monthlySalary": undefined,
"specialization": "Front End", specialization: 'Front End',
"title": "Software Engineer", title: 'Software Engineer',
"totalCompensation": { totalCompensation: {
"currency": "SGD", currency: 'SGD',
"value": 104100 value: 104100,
} },
} },
], ],
"specificYoes": [ specificYoes: [
{ {
"domain": "Front End", domain: 'Front End',
"yoe": 2 yoe: 2,
}, },
{ {
"domain": "Full Stack", domain: 'Full Stack',
"yoe": 2 yoe: 2,
} },
], ],
"totalYoe": 4 totalYoe: 4,
}, },
"offers": [ offers: [
{ {
"comments": "", comments: '',
"companyId": "cl92szctf0008i9nfxk54bhxn", companyId: 'cl93m87pl0000tx1ofbafqz6f',
"job": { job: {
"base": { base: {
"currency": "SGD", currency: 'SGD',
"value": 84000 value: 84000,
}, },
"bonus": { bonus: {
"currency": "SGD", currency: 'SGD',
"value": 20000 value: 20000,
}, },
"level": "Junior", level: 'Junior',
"specialization": "Front End", specialization: 'Front End',
"stocks": { stocks: {
"currency": "SGD", currency: 'SGD',
"value": 100 value: 100,
}, },
"title": "Software Engineer", title: 'Software Engineer',
"totalCompensation": { totalCompensation: {
"currency": "SGD", currency: 'SGD',
"value": 104100 value: 104100,
} },
}, },
"jobType": "FULLTIME", jobType: 'FULLTIME',
"location": "Singapore, Singapore", location: 'Singapore, Singapore',
"monthYearReceived": new Date("2022-09-30T07:58:54.000Z"), monthYearReceived: new Date('2022-09-30T07:58:54.000Z'),
"negotiationStrategy": "Leveraged having multiple offers" negotiationStrategy: 'Leveraged having multiple offers',
}, },
{ {
"comments": "", comments: '',
"companyId": "cl92szctf0008i9nfxk54bhxn", companyId: 'cl93m87pl0000tx1ofbafqz6f',
"job": { job: {
"base": { base: {
"currency": "SGD", currency: 'SGD',
"value": 84000 value: 84000,
}, },
"bonus": { bonus: {
"currency": "SGD", currency: 'SGD',
"value": 20000 value: 20000,
}, },
"level": "Junior", level: 'Junior',
"specialization": "Front End", specialization: 'Front End',
"stocks": { stocks: {
"currency": "SGD", currency: 'SGD',
"value": 100 value: 100,
}, },
"title": "Software Engineer", title: 'Software Engineer',
"totalCompensation": { totalCompensation: {
"currency": "SGD", currency: 'SGD',
"value": 104100 value: 104100,
} },
}, },
"jobType": "FULLTIME", jobType: 'FULLTIME',
"location": "Singapore, Singapore", location: 'Singapore, Singapore',
"monthYearReceived": new Date("2022-09-30T07:58:54.000Z"), monthYearReceived: new Date('2022-09-30T07:58:54.000Z'),
"negotiationStrategy": "Leveraged having multiple offers" negotiationStrategy: 'Leveraged having multiple offers',
} },
] ],
}); });
}; };
const profileId = 'cl92wiw30006vw3hg7dxa14fo'; // Remember to change this filed after testing deleting
const data = trpc.useQuery([ const data = trpc.useQuery([
`offers.profile.listOne`, `offers.profile.listOne`,
{ {
profileId: "cl92wc64a004gw3hgq4pfln2m" profileId,
} },
]) ]);
const deleteMutation = trpc.useMutation(['offers.profile.delete']);
const handleDelete = (id: string) => {
deleteMutation.mutate({ id });
};
return ( return (
// <ul> // <ul>
@ -141,10 +147,18 @@ function Test() {
// })} // })}
// </ul> // </ul>
<> <>
<div> <div>{createdData}</div>
{createdData} <button type="button" onClick={handleClick}>
</div> Click Me!
<button type="button" onClick={handleClick}>Click Me!</button> </button>
<button
className="text-danger-600"
type="button"
onClick={() => {
handleDelete(profileId);
}}>
DELETE THIS PROFILE
</button>
<div>{JSON.stringify(data.data)}</div> <div>{JSON.stringify(data.data)}</div>
{/* <button type="button" onClick}>Get One</button> */} {/* <button type="button" onClick}>Get One</button> */}

@ -1,13 +1,13 @@
import crypto, { randomUUID } from "crypto"; import crypto, { randomUUID } from 'crypto';
import { z } from "zod"; import { z } from 'zod';
import { Prisma } from "@prisma/client"; import { Prisma } from '@prisma/client';
import { createRouter } from "./context"; import { createRouter } from './context';
const valuation = z.object({ const valuation = z.object({
currency: z.string(), currency: z.string(),
value: z.number(), value: z.number(),
}) });
// TODO: handle both full time and intern // TODO: handle both full time and intern
const offer = z.object({ const offer = z.object({
@ -29,7 +29,7 @@ const offer = z.object({
location: z.string(), location: z.string(),
monthYearReceived: z.date(), monthYearReceived: z.date(),
negotiationStrategy: z.string(), negotiationStrategy: z.string(),
}) });
const experience = z.object({ const experience = z.object({
companyId: z.string().optional(), companyId: z.string().optional(),
@ -40,7 +40,7 @@ const experience = z.object({
specialization: z.string().optional(), specialization: z.string().optional(),
title: z.string().optional(), title: z.string().optional(),
totalCompensation: valuation.optional(), totalCompensation: valuation.optional(),
}) });
const education = z.object({ const education = z.object({
endDate: z.date().optional(), endDate: z.date().optional(),
@ -48,7 +48,7 @@ const education = z.object({
school: z.string().optional(), school: z.string().optional(),
startDate: z.date().optional(), startDate: z.date().optional(),
type: z.string().optional(), type: z.string().optional(),
}) });
export const offersProfileRouter = createRouter() export const offersProfileRouter = createRouter()
.query('listOne', { .query('listOne', {
@ -65,17 +65,17 @@ export const offersProfileRouter = createRouter()
include: { include: {
company: true, company: true,
monthlySalary: true, monthlySalary: true,
totalCompensation: true totalCompensation: true,
} },
},
specificYoes: true,
}, },
specificYoes: true
}
}, },
discussion: { discussion: {
include: { include: {
replies: true, replies: true,
replyingTo: true replyingTo: true,
} },
}, },
offers: { offers: {
include: { include: {
@ -84,70 +84,71 @@ export const offersProfileRouter = createRouter()
baseSalary: true, baseSalary: true,
bonus: true, bonus: true,
stocks: true, stocks: true,
totalCompensation: true totalCompensation: true,
} },
}, },
OffersIntern: { OffersIntern: {
include: { include: {
monthlySalary: true monthlySalary: true,
} },
},
company: true,
},
}, },
company: true
}
}
}, },
where: { where: {
id: input.profileId id: input.profileId,
} },
}) });
} },
}) })
.mutation( .mutation('create', {
'create',
{
input: z.object({ input: z.object({
background: z.object({ background: z.object({
educations: z.array(education), educations: z.array(education),
experiences: z.array(experience), experiences: z.array(experience),
specificYoes: z.array(z.object({ specificYoes: z.array(
z.object({
domain: z.string(), domain: z.string(),
yoe: z.number(), yoe: z.number(),
})), }),
),
totalYoe: z.number().optional(), totalYoe: z.number().optional(),
}), }),
offers: z.array(offer) offers: z.array(offer),
}), }),
async resolve({ ctx, input }) { async resolve({ ctx, input }) {
// TODO: add more // TODO: add more
const token = crypto const token = crypto
.createHash("sha256") .createHash('sha256')
.update(Date.now().toString()) .update(Date.now().toString())
.digest("hex"); .digest('hex');
const profile = await ctx.prisma.offersProfile.create({ const profile = await ctx.prisma.offersProfile.create({
data: { data: {
background: { background: {
create: { create: {
educations: { educations: {
create: create: input.background.educations.map((x) => ({
input.background.educations.map((x) => ({
endDate: x.endDate, endDate: x.endDate,
field: x.field, field: x.field,
school: x.school, school: x.school,
startDate: x.startDate, startDate: x.startDate,
type: x.type type: x.type,
})) })),
}, },
experiences: { experiences: {
create: create: input.background.experiences.map((x) => {
input.background.experiences.map((x) => { if (
if (x.jobType === "FULLTIME" && x.totalCompensation?.currency !== undefined && x.totalCompensation.value !== undefined) { x.jobType === 'FULLTIME' &&
x.totalCompensation?.currency !== undefined &&
x.totalCompensation.value !== undefined
) {
return { return {
company: { company: {
connect: { connect: {
id: x.companyId id: x.companyId,
} },
}, },
durationInMonths: x.durationInMonths, durationInMonths: x.durationInMonths,
jobType: x.jobType, jobType: x.jobType,
@ -158,51 +159,58 @@ export const offersProfileRouter = createRouter()
create: { create: {
currency: x.totalCompensation?.currency, currency: x.totalCompensation?.currency,
value: x.totalCompensation?.value, value: x.totalCompensation?.value,
}
}, },
},
};
} }
} if (
if (x.jobType === "INTERN" && x.monthlySalary?.currency !== undefined && x.monthlySalary.value !== undefined) { x.jobType === 'INTERN' &&
x.monthlySalary?.currency !== undefined &&
x.monthlySalary.value !== undefined
) {
return { return {
company: { company: {
connect: { connect: {
id: x.companyId id: x.companyId,
} },
}, },
durationInMonths: x.durationInMonths, durationInMonths: x.durationInMonths,
jobType: x.jobType, jobType: x.jobType,
monthlySalary: { monthlySalary: {
create: { create: {
currency: x.monthlySalary?.currency, currency: x.monthlySalary?.currency,
value: x.monthlySalary?.value value: x.monthlySalary?.value,
} },
}, },
specialization: x.specialization, specialization: x.specialization,
title: x.title, title: x.title,
};
} }
}
throw Prisma.PrismaClientKnownRequestError
}) throw Prisma.PrismaClientKnownRequestError;
}),
}, },
specificYoes: { specificYoes: {
create: create: input.background.specificYoes.map((x) => {
input.background.specificYoes.map((x) => {
return { return {
domain: x.domain, domain: x.domain,
yoe: x.yoe yoe: x.yoe,
} };
}) }),
}, },
totalYoe: input.background.totalYoe, totalYoe: input.background.totalYoe,
} },
}, },
editToken: token, editToken: token,
offers: { offers: {
create: create: input.offers.map((x) => {
input.offers.map((x) => { if (
if (x.jobType === "INTERN" && x.job.internshipCycle !== undefined && x.job.monthlySalary?.currency !== undefined && x.job.monthlySalary.value !== undefined && x.job.startYear !== undefined) { x.jobType === 'INTERN' &&
x.job.internshipCycle !== undefined &&
x.job.monthlySalary?.currency !== undefined &&
x.job.monthlySalary.value !== undefined &&
x.job.startYear !== undefined
) {
return { return {
OffersIntern: { OffersIntern: {
create: { create: {
@ -210,41 +218,52 @@ export const offersProfileRouter = createRouter()
monthlySalary: { monthlySalary: {
create: { create: {
currency: x.job.monthlySalary?.currency, currency: x.job.monthlySalary?.currency,
value: x.job.monthlySalary?.value value: x.job.monthlySalary?.value,
} },
}, },
specialization: x.job.specialization, specialization: x.job.specialization,
startYear: x.job.startYear, startYear: x.job.startYear,
title: x.job.title, title: x.job.title,
} },
}, },
comments: x.comments, comments: x.comments,
company: { company: {
connect: { connect: {
id: x.companyId id: x.companyId,
} },
}, },
jobType: x.jobType, jobType: x.jobType,
location: x.location, location: x.location,
monthYearReceived: x.monthYearReceived, monthYearReceived: x.monthYearReceived,
negotiationStrategy: x.negotiationStrategy negotiationStrategy: x.negotiationStrategy,
} };
} }
if (x.jobType === "FULLTIME" && x.job.base?.currency !== undefined && x.job.base?.value !== undefined && x.job.bonus?.currency !== undefined && x.job.bonus?.value !== undefined && x.job.stocks?.currency !== undefined && x.job.stocks?.value !== undefined && x.job.totalCompensation?.currency !== undefined && x.job.totalCompensation?.value !== undefined && x.job.level !== undefined) { if (
x.jobType === 'FULLTIME' &&
x.job.base?.currency !== undefined &&
x.job.base?.value !== undefined &&
x.job.bonus?.currency !== undefined &&
x.job.bonus?.value !== undefined &&
x.job.stocks?.currency !== undefined &&
x.job.stocks?.value !== undefined &&
x.job.totalCompensation?.currency !== undefined &&
x.job.totalCompensation?.value !== undefined &&
x.job.level !== undefined
) {
return { return {
OffersFullTime: { OffersFullTime: {
create: { create: {
baseSalary: { baseSalary: {
create: { create: {
currency: x.job.base?.currency, currency: x.job.base?.currency,
value: x.job.base?.value value: x.job.base?.value,
} },
}, },
bonus: { bonus: {
create: { create: {
currency: x.job.bonus?.currency, currency: x.job.bonus?.currency,
value: x.job.bonus?.value value: x.job.bonus?.value,
} },
}, },
level: x.job.level, level: x.job.level,
specialization: x.job.specialization, specialization: x.job.specialization,
@ -252,35 +271,35 @@ export const offersProfileRouter = createRouter()
create: { create: {
currency: x.job.stocks?.currency, currency: x.job.stocks?.currency,
value: x.job.stocks?.value, value: x.job.stocks?.value,
} },
}, },
title: x.job.title, title: x.job.title,
totalCompensation: { totalCompensation: {
create: { create: {
currency: x.job.totalCompensation?.currency, currency: x.job.totalCompensation?.currency,
value: x.job.totalCompensation?.value, value: x.job.totalCompensation?.value,
}
}, },
} },
},
}, },
comments: x.comments, comments: x.comments,
company: { company: {
connect: { connect: {
id: x.companyId id: x.companyId,
} },
}, },
jobType: x.jobType, jobType: x.jobType,
location: x.location, location: x.location,
monthYearReceived: x.monthYearReceived, monthYearReceived: x.monthYearReceived,
negotiationStrategy: x.negotiationStrategy negotiationStrategy: x.negotiationStrategy,
} };
} }
// Throw error // Throw error
throw Prisma.PrismaClientKnownRequestError throw Prisma.PrismaClientKnownRequestError;
}) }),
}, },
profileName: randomUUID().substring(0,10), profileName: randomUUID().substring(0, 10),
}, },
include: { include: {
background: { background: {
@ -290,11 +309,11 @@ export const offersProfileRouter = createRouter()
include: { include: {
company: true, company: true,
monthlySalary: true, monthlySalary: true,
totalCompensation: true totalCompensation: true,
} },
},
specificYoes: true,
}, },
specificYoes: true
}
}, },
offers: { offers: {
include: { include: {
@ -303,21 +322,32 @@ export const offersProfileRouter = createRouter()
baseSalary: true, baseSalary: true,
bonus: true, bonus: true,
stocks: true, stocks: true,
totalCompensation: true totalCompensation: true,
} },
}, },
OffersIntern: { OffersIntern: {
include: { include: {
monthlySalary: true monthlySalary: true,
} },
} },
} },
} },
}, },
}); });
// TODO: add analysis to profile object then return // TODO: add analysis to profile object then return
return profile return profile;
}
}, },
); })
.mutation('delete', {
input: z.object({
id: z.string(),
}),
async resolve({ ctx, input }) {
return await ctx.prisma.offersProfile.delete({
where: {
id: input.id,
},
});
},
});

@ -200,6 +200,7 @@ export const offersRouter = createRouter().query('list', {
}, },
}); });
// FILTERING
data = data.filter((offer) => { data = data.filter((offer) => {
let validRecord = true; let validRecord = true;
@ -235,6 +236,7 @@ export const offersRouter = createRouter().query('list', {
return validRecord; return validRecord;
}); });
// SORTING
data = data.sort((offer1, offer2) => { data = data.sort((offer1, offer2) => {
const defaultReturn = const defaultReturn =
offer2.monthYearReceived.getTime() - offer1.monthYearReceived.getTime(); offer2.monthYearReceived.getTime() - offer1.monthYearReceived.getTime();

Loading…
Cancel
Save