From 68d0956cba7dbfea479572f3af8e32eee1a8d2af Mon Sep 17 00:00:00 2001
From: Stuart Long Chay Boon <chayboon@gmail.com>
Date: Fri, 14 Oct 2022 00:40:40 +0800
Subject: [PATCH] [offers][feat] add edit profile endpoint

---
 .../src/pages/offers/test/createProfile.tsx   | 392 +++++++++-
 .../router/offers/offers-profile-router.ts    | 707 ++++++++++++++++--
 2 files changed, 1028 insertions(+), 71 deletions(-)

diff --git a/apps/portal/src/pages/offers/test/createProfile.tsx b/apps/portal/src/pages/offers/test/createProfile.tsx
index 9c21d52c..5b42a76f 100644
--- a/apps/portal/src/pages/offers/test/createProfile.tsx
+++ b/apps/portal/src/pages/offers/test/createProfile.tsx
@@ -66,10 +66,9 @@ function Test() {
       },
       offers: [
         {
-          // Comments: '',
-          companyId: 'cl95u79f000007im531ysjg79',
-          job: {
-            base: {
+
+          OffersFullTime: {
+            baseSalary: {
               currency: 'SGD',
               value: 84000,
             },
@@ -89,16 +88,16 @@ function Test() {
               value: 104100,
             },
           },
+          // Comments: '',
+          companyId: 'cl95u79f000007im531ysjg79',
           jobType: 'FULLTIME',
           location: 'Singapore, Singapore',
           monthYearReceived: new Date('2022-09-30T07:58:54.000Z'),
           negotiationStrategy: 'Leveraged having multiple offers',
         },
         {
-          comments: undefined,
-          companyId: 'cl95u79f000007im531ysjg79',
-          job: {
-            base: {
+          OffersFullTime: {
+            baseSalary: {
               currency: 'SGD',
               value: 84000,
             },
@@ -118,6 +117,8 @@ function Test() {
               value: 104100,
             },
           },
+          comments: undefined,
+          companyId: 'cl95u79f000007im531ysjg79',
           jobType: 'FULLTIME',
           location: 'Singapore, Singapore',
           monthYearReceived: new Date('2022-09-30T07:58:54.000Z'),
@@ -127,12 +128,12 @@ function Test() {
     });
   };
 
-  const profileId = 'cl95u9ju500eo7ipd54kurv8d'; // Remember to change this filed after testing deleting
+  const profileId = 'cl96stky5002ew32gx2kale2x'; // Remember to change this filed after testing deleting
   const data = trpc.useQuery([
     `offers.profile.listOne`,
     {
       profileId,
-      token: 'dccc05133962013ba8b4ee396e51baee1b53a66051732b48fd015129ae1d593e',
+      token: 'afca11e436d21bde24543718fa957c6c625335439dc504f24ee35eae7b5ef1ba',
     },
   ], {
     onError(err) {
@@ -145,16 +146,385 @@ function Test() {
   const handleDelete = (id: string) => {
     deleteMutation.mutate({
       profileId: id,
-      token: 'dccc05133962013ba8b4ee396e51baee1b53a66051732b48fd015129ae1d593e',
+      token: 'afca11e436d21bde24543718fa957c6c625335439dc504f24ee35eae7b5ef1ba',
     });
   };
 
+  const updateMutation = trpc.useMutation(['offers.profile.update'], {
+    onError(err: any) {
+      alert(err);
+    },
+    onSuccess(response) {
+      setCreatedData(JSON.stringify(response));
+    },
+  });
+
+  const handleUpdate = () => {
+    updateMutation.mutate({
+      background: {
+        educations: [
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            endDate: new Date("2018-09-30T07:58:54.000Z"),
+            field: "Computer Science",
+            id: "cl96stky6002gw32gey2ffawd",
+            school: "National University of Singapore",
+            startDate: new Date("2014-09-30T07:58:54.000Z"),
+            type: "Bachelors"
+          }
+        ],
+        experiences: [
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            company: {
+              createdAt: new Date("2022-10-12T16:19:05.196Z"),
+              description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook, Inc., is an American multinational technology conglomerate based in Menlo Park, California. The company owns Facebook, Instagram, and WhatsApp, among other products and services.",
+              id: "cl95u79f000007im531ysjg79",
+              logoUrl: "https://logo.clearbit.com/meta.com",
+              name: "Meta",
+              slug: "meta",
+              updatedAt: new Date("2022-10-12T16:19:05.196Z")
+            },
+            companyId: "cl95u79f000007im531ysjg79",
+            durationInMonths: 24,
+            id: "cl96stky6002iw32gpt6t87s2",
+            jobType: "FULLTIME",
+            level: "Junior",
+            monthlySalary: null,
+            monthlySalaryId: null,
+            specialization: "Front End",
+            title: "Software Engineer",
+            totalCompensation: {
+              currency: "SGD",
+              id: "cl96stky6002jw32g73svfacr",
+              value: 104100
+            },
+            totalCompensationId: "cl96stky6002jw32g73svfacr"
+          }
+        ],
+        id: "cl96stky6002fw32g6vj4meyr",
+        offersProfileId: "cl96stky5002ew32gx2kale2x",
+        specificYoes: [
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            domain: "Backend",
+            id: "cl96t7890004tw32g5in3px5j",
+            yoe: 2
+          },
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            domain: "Backend",
+            id: "cl96tb87x004xw32gnu17jbzv",
+            yoe: 2
+          },
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            domain: "Backend",
+            id: "cl976t39z00007iygt3np3cgo",
+            yoe: 2
+          },
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            domain: "Front End",
+            id: "cl96stky7002mw32gn4jc7uml",
+            yoe: 2
+          },
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            domain: "Full Stack",
+            id: "cl96stky7002nw32gpprghtxr",
+            yoe: 2
+          },
+          {
+            backgroundId: "cl96stky6002fw32g6vj4meyr",
+            domain: "Backend",
+            id: "cl976we5h000p7iygiomdo9fh",
+            yoe: 2
+          }
+        ],
+        totalYoe: 6
+      },
+      createdAt: "2022-10-13T08:28:13.518Z",
+      discussion: [],
+      id: "cl96stky5002ew32gx2kale2x",
+      isEditable: true,
+      offers: [
+        {
+          OffersFullTime: {
+            baseSalary: {
+              currency: "SGD",
+              id: "cl976t4de00067iyg3pjir7k9",
+              value: 1999999999
+            },
+            baseSalaryId: "cl976t4de00067iyg3pjir7k9",
+            bonus: {
+              currency: "SGD",
+              id: "cl976t4de00087iygcnlmh8aw",
+              value: 1410065407
+            },
+            bonusId: "cl976t4de00087iygcnlmh8aw",
+            id: "cl976t4de00057iygq3ktce3v",
+            level: "EXPERT",
+            specialization: "FRONTEND",
+            stocks: {
+              currency: "SGD",
+              id: "cl976t4df000a7iygkrsgr1xh",
+              value: -558038585
+            },
+            stocksId: "cl976t4df000a7iygkrsgr1xh",
+            title: "Software Engineer",
+            totalCompensation: {
+              currency: "SGD",
+              id: "cl976t4df000c7iyg73ryf5uw",
+              value: 55555555
+            },
+            totalCompensationId: "cl976t4df000c7iyg73ryf5uw"
+          },
+          OffersIntern: null,
+          comments: "this IS SO IEUHDAEUIGDI",
+          company: {
+            createdAt: new Date("2022-10-12T16:19:05.196Z"),
+            description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook, Inc., is an American multinational technology conglomerate based in Menlo Park, California. The company owns Facebook, Instagram, and WhatsApp, among other products and services.",
+            id: "cl95u79f000007im531ysjg79",
+            logoUrl: "https://logo.clearbit.com/meta.com",
+            name: "Meta",
+            slug: "meta",
+            updatedAt: new Date("2022-10-12T16:19:05.196Z")
+          },
+          companyId: "cl95u79f000007im531ysjg79",
+          id: "cl976t4de00047iygl0zbce11",
+          jobType: "FULLTIME",
+          location: "Singapore, Singapore",
+          monthYearReceived: new Date("2022-09-30T07:58:54.000Z"),
+          negotiationStrategy: "Charmed the guy with my face",
+          offersFullTimeId: "cl976t4de00057iygq3ktce3v",
+          offersInternId: null,
+          profileId: "cl96stky5002ew32gx2kale2x"
+        },
+        {
+          OffersFullTime: {
+            baseSalary: {
+              currency: "SGD",
+              id: "cl96stky80033w32gxw5goc4z",
+              value: 84000
+            },
+            baseSalaryId: "cl96stky80033w32gxw5goc4z",
+            bonus: {
+              currency: "SGD",
+              id: "cl96stky80035w32gajjwdo1p",
+              value: 123456789
+            },
+            bonusId: "cl96stky80035w32gajjwdo1p",
+            id: "cl96stky80032w32gep9ovgj3",
+            level: "Junior",
+            specialization: "Front End",
+            stocks: {
+              currency: "SGD",
+              id: "cl96stky90037w32gu04t6ybh",
+              value: 100
+            },
+            stocksId: "cl96stky90037w32gu04t6ybh",
+            title: "Software Engineer",
+            totalCompensation: {
+              currency: "SGD",
+              id: "cl96stky90039w32glbpktd0o",
+              value: 104100
+            },
+            totalCompensationId: "cl96stky90039w32glbpktd0o"
+          },
+          OffersIntern: null,
+          comments: null,
+          company: {
+            createdAt: new Date("2022-10-12T16:19:05.196Z"),
+            description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook, Inc., is an American multinational technology conglomerate based in Menlo Park, California. The company owns Facebook, Instagram, and WhatsApp, among other products and services.",
+            id: "cl95u79f000007im531ysjg79",
+            logoUrl: "https://logo.clearbit.com/meta.com",
+            name: "Meta",
+            slug: "meta",
+            updatedAt: new Date("2022-10-12T16:19:05.196Z")
+          },
+          companyId: "cl95u79f000007im531ysjg79",
+          id: "cl96stky80031w32gau9mu1gs",
+          jobType: "FULLTIME",
+          location: "Singapore, Singapore",
+          monthYearReceived: new Date("2022-09-30T07:58:54.000Z"),
+          negotiationStrategy: "Leveraged having million offers",
+          offersFullTimeId: "cl96stky80032w32gep9ovgj3",
+          offersInternId: null,
+          profileId: "cl96stky5002ew32gx2kale2x"
+        },
+        {
+          OffersFullTime: {
+            baseSalary: {
+              currency: "SGD",
+              id: "cl96stky9003dw32gcvqbijlo",
+              value: 1
+            },
+            baseSalaryId: "cl96stky9003dw32gcvqbijlo",
+            bonus: {
+              currency: "SGD",
+              id: "cl96stky9003fw32goc3zqxwr",
+              value: 0
+            },
+            bonusId: "cl96stky9003fw32goc3zqxwr",
+            id: "cl96stky9003cw32g5v10izfu",
+            level: "Senior",
+            specialization: "Front End",
+            stocks: {
+              currency: "SGD",
+              id: "cl96stky9003hw32g1lbbkqqr",
+              value: 999999
+            },
+            stocksId: "cl96stky9003hw32g1lbbkqqr",
+            title: "Software Engineer DOG",
+            totalCompensation: {
+              currency: "SGD",
+              id: "cl96stky9003jw32gzumcoi7v",
+              value: 999999
+            },
+            totalCompensationId: "cl96stky9003jw32gzumcoi7v"
+          },
+          OffersIntern: null,
+          comments: null,
+          company: {
+            createdAt: new Date("2022-10-12T16:19:05.196Z"),
+            description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook, Inc., is an American multinational technology conglomerate based in Menlo Park, California. The company owns Facebook, Instagram, and WhatsApp, among other products and services.",
+            id: "cl95u79f000007im531ysjg79",
+            logoUrl: "https://logo.clearbit.com/meta.com",
+            name: "Meta",
+            slug: "meta",
+            updatedAt: new Date("2022-10-12T16:19:05.196Z")
+          },
+          companyId: "cl95u79f000007im531ysjg79",
+          id: "cl96stky9003bw32gc3l955vr",
+          jobType: "FULLTIME",
+          location: "Singapore, Singapore",
+          monthYearReceived: new Date("2022-09-30T07:58:54.000Z"),
+          negotiationStrategy: "LOst out having multiple offers",
+          offersFullTimeId: "cl96stky9003cw32g5v10izfu",
+          offersInternId: null,
+          profileId: "cl96stky5002ew32gx2kale2x"
+        },
+        {
+          OffersFullTime: {
+            baseSalary: {
+              currency: "SGD",
+              id: "cl976wf28000v7iygmk1b7qaq",
+              value: 1999999999
+            },
+            baseSalaryId: "cl976wf28000v7iygmk1b7qaq",
+            bonus: {
+              currency: "SGD",
+              id: "cl976wf28000x7iyg63w7kcli",
+              value: 1410065407
+            },
+            bonusId: "cl976wf28000x7iyg63w7kcli",
+            id: "cl976wf28000u7iyg6euei8e9",
+            level: "EXPERT",
+            specialization: "FRONTEND",
+            stocks: {
+              currency: "SGD",
+              id: "cl976wf28000z7iyg9ivun6ap",
+              value: 111222333
+            },
+            stocksId: "cl976wf28000z7iyg9ivun6ap",
+            title: "Software Engineer",
+            totalCompensation: {
+              currency: "SGD",
+              id: "cl976wf2800117iygmzsc0xit",
+              value: 55555555
+            },
+            totalCompensationId: "cl976wf2800117iygmzsc0xit"
+          },
+          OffersIntern: null,
+          comments: "this IS SO COOL",
+          company: {
+            createdAt: new Date("2022-10-12T16:19:05.196Z"),
+            description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook, Inc., is an American multinational technology conglomerate based in Menlo Park, California. The company owns Facebook, Instagram, and WhatsApp, among other products and services.",
+            id: "cl95u79f000007im531ysjg79",
+            logoUrl: "https://logo.clearbit.com/meta.com",
+            name: "Meta",
+            slug: "meta",
+            updatedAt: new Date("2022-10-12T16:19:05.196Z")
+          },
+          companyId: "cl95u79f000007im531ysjg79",
+          id: "cl976wf28000t7iyga4noyz7s",
+          jobType: "FULLTIME",
+          location: "Singapore, Singapore",
+          monthYearReceived: new Date("2022-09-30T07:58:54.000Z"),
+          negotiationStrategy: "Charmed the guy with my face",
+          offersFullTimeId: "cl976wf28000u7iyg6euei8e9",
+          offersInternId: null,
+          profileId: "cl96stky5002ew32gx2kale2x"
+        },
+        {
+          OffersFullTime: {
+            baseSalary: {
+              currency: "SGD",
+              id: "cl96tbb3o0053w32gz11paaxu",
+              value: 1999999999
+            },
+            baseSalaryId: "cl96tbb3o0053w32gz11paaxu",
+            bonus: {
+              currency: "SGD",
+              id: "cl96tbb3o0055w32gpyqgz5hx",
+              value: 1410065407
+            },
+            bonusId: "cl96tbb3o0055w32gpyqgz5hx",
+            id: "cl96tbb3o0052w32guguajzin",
+            level: "EXPERT",
+            specialization: "FRONTEND",
+            stocks: {
+              currency: "SGD",
+              id: "cl96tbb3o0057w32gu4nyxguf",
+              value: 500
+            },
+            stocksId: "cl96tbb3o0057w32gu4nyxguf",
+            title: "Software Engineer",
+            totalCompensation: {
+              currency: "SGD",
+              id: "cl96tbb3o0059w32gm3iy1zk4",
+              value: 55555555
+            },
+            totalCompensationId: "cl96tbb3o0059w32gm3iy1zk4"
+          },
+          OffersIntern: null,
+          comments: "this rocks",
+          company: {
+            createdAt: new Date("2022-10-12T16:19:05.196Z"),
+            description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook, Inc., is an American multinational technology conglomerate based in Menlo Park, California. The company owns Facebook, Instagram, and WhatsApp, among other products and services.",
+            id: "cl95u79f000007im531ysjg79",
+            logoUrl: "https://logo.clearbit.com/meta.com",
+            name: "Meta",
+            slug: "meta",
+            updatedAt: new Date("2022-10-12T16:19:05.196Z")
+          },
+          companyId: "cl95u79f000007im531ysjg79",
+          id: "cl96tbb3o0051w32gjrpaiiit",
+          jobType: "FULLTIME",
+          location: "Singapore, Singapore",
+          monthYearReceived: new Date("2022-09-30T07:58:54.000Z"),
+          negotiationStrategy: "Charmed the guy with my face",
+          offersFullTimeId: "cl96tbb3o0052w32guguajzin",
+          offersInternId: null,
+          profileId: "cl96stky5002ew32gx2kale2x"
+        }
+      ],
+      profileName: "ailing bryann stuart ziqing",
+      token: "afca11e436d21bde24543718fa957c6c625335439dc504f24ee35eae7b5ef1ba",
+      userId: null
+    });
+  }
+
   return (
     <>
       <div>{createdData}</div>
       <button type="button" onClick={handleClick}>
         Click Me!
       </button>
+      <button type="button" onClick={handleUpdate}>
+        UPDATE!
+      </button>
       <button
         className="text-danger-600"
         type="button"
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 1876010a..a4d4ee64 100644
--- a/apps/portal/src/server/router/offers/offers-profile-router.ts
+++ b/apps/portal/src/server/router/offers/offers-profile-router.ts
@@ -9,50 +9,92 @@ import type { offersProfile } from '~/types/offers-profile';
 
 const valuation = z.object({
   currency: z.string(),
+  id: z.string().optional(),
   value: z.number(),
 });
 
-// TODO: handle both full time and intern
+const company = z.object({
+  createdAt: z.date(),
+  description: z.string().nullish(),
+  id: z.string().optional(),
+  logoUrl: z.string().nullish(),
+  name: z.string(),
+  slug: z.string(),
+  updatedAt: z.date()
+})
+
 const offer = z.object({
-  comments: z.string().optional(),
-  companyId: z.string(),
-  job: z.object({
-    base: valuation.optional(), // Full time
-    bonus: valuation.optional(), // Full time
-    internshipCycle: z.string().optional(), // Intern
-    level: z.string().optional(), // Full time
-    monthlySalary: valuation.optional(), // Intern
+  OffersFullTime: z.object({
+    baseSalary: valuation.nullish(),
+    baseSalaryId: z.string().nullish(),
+    bonus: valuation.nullish(),
+    bonusId: z.string().nullish(),
+    id: z.string().optional(),
+    level: z.string().nullish(),
     specialization: z.string(),
-    startYear: z.number().optional(), // Intern
-    stocks: valuation.optional(), // Full time
+    stocks: valuation.nullish(),
+    stocksId: z.string().nullish(),
     title: z.string(),
-    totalCompensation: valuation.optional(), // Full time
-  }),
+    totalCompensation: valuation.nullish(),
+    totalCompensationId: z.string().nullish(),
+  }).nullish(),
+  OffersIntern: z.object({
+    id: z.string().optional(),
+    internshipCycle: z.string().nullish(),
+    monthlySalary: valuation.nullish(),
+    specialization: z.string(),
+    startYear: z.number().nullish(),
+    title: z.string(),
+    totalCompensation: valuation.nullish(), // Full time
+  }).nullish(),
+  comments: z.string().nullish(),
+  company: company.nullish(),
+  companyId: z.string(),
+  id: z.string().optional(),
   jobType: z.string(),
   location: z.string(),
   monthYearReceived: z.date(),
-  negotiationStrategy: z.string().optional(),
+  negotiationStrategy: z.string().nullish(),
+  offersFullTimeId: z.string().nullish(),
+  offersInternId: z.string().nullish(),
+  profileId: z.string().nullish(),
 });
 
 const experience = z.object({
-  companyId: z.string().optional(),
-  durationInMonths: z.number().optional(),
-  jobType: z.string().optional(),
-  level: z.string().optional(),
-  monthlySalary: valuation.optional(),
-  specialization: z.string().optional(),
-  title: z.string().optional(),
-  totalCompensation: valuation.optional(),
+  backgroundId: z.string().nullish(),
+  company: company.nullish(),
+  companyId: z.string().nullish(),
+  durationInMonths: z.number().nullish(),
+  id: z.string().optional(),
+  jobType: z.string().nullish(),
+  level: z.string().nullish(),
+  monthlySalary: valuation.nullish(),
+  monthlySalaryId: z.string().nullish(),
+  specialization: z.string().nullish(),
+  title: z.string().nullish(),
+  totalCompensation: valuation.nullish(),
+  totalCompensationId: z.string().nullish()
 });
 
 const education = z.object({
-  endDate: z.date().optional(),
-  field: z.string().optional(),
-  school: z.string().optional(),
-  startDate: z.date().optional(),
-  type: z.string().optional(),
+  backgroundId: z.string().nullish(),
+  endDate: z.date().nullish(),
+  field: z.string().nullish(),
+  id: z.string().optional(),
+  school: z.string().nullish(),
+  startDate: z.date().nullish(),
+  type: z.string().nullish(),
 });
 
+const reply = z.object({
+  createdAt: z.date().nullish(),
+  id: z.string().optional(),
+  messages: z.string().nullish(),
+  profileId: z.string().nullish(),
+  replyingToId: z.string().nullish(),
+  userId: z.string().nullish()
+})
+
 type WithIsEditable<T> = T & {
   isEditable: boolean;
 };
@@ -272,24 +314,25 @@ export const offersProfileRouter = createRouter()
             create: input.offers.map((x) => {
               if (
                 x.jobType === 'INTERN' &&
-                x.job.internshipCycle !== undefined &&
-                x.job.monthlySalary?.currency !== undefined &&
-                x.job.monthlySalary.value !== undefined &&
-                x.job.startYear !== undefined
+                x.OffersIntern &&
+                x.OffersIntern.internshipCycle &&
+                x.OffersIntern.monthlySalary?.currency &&
+                x.OffersIntern.monthlySalary.value &&
+                x.OffersIntern.startYear
               ) {
                 return {
                   OffersIntern: {
                     create: {
-                      internshipCycle: x.job.internshipCycle,
+                      internshipCycle: x.OffersIntern.internshipCycle,
                       monthlySalary: {
                         create: {
-                          currency: x.job.monthlySalary?.currency,
-                          value: x.job.monthlySalary?.value,
+                          currency: x.OffersIntern.monthlySalary?.currency,
+                          value: x.OffersIntern.monthlySalary?.value,
                         },
                       },
-                      specialization: x.job.specialization,
-                      startYear: x.job.startYear,
-                      title: x.job.title,
+                      specialization: x.OffersIntern.specialization,
+                      startYear: x.OffersIntern.startYear,
+                      title: x.OffersIntern.title,
                     },
                   },
                   comments: x.comments,
@@ -306,44 +349,45 @@ export const offersProfileRouter = createRouter()
               }
               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
+                x.OffersFullTime &&
+                x.OffersFullTime.baseSalary?.currency &&
+                x.OffersFullTime.baseSalary?.value &&
+                x.OffersFullTime.bonus?.currency &&
+                x.OffersFullTime.bonus?.value &&
+                x.OffersFullTime.stocks?.currency &&
+                x.OffersFullTime.stocks?.value &&
+                x.OffersFullTime.totalCompensation?.currency &&
+                x.OffersFullTime.totalCompensation?.value &&
+                x.OffersFullTime.level
               ) {
                 return {
                   OffersFullTime: {
                     create: {
                       baseSalary: {
                         create: {
-                          currency: x.job.base?.currency,
-                          value: x.job.base?.value,
+                          currency: x.OffersFullTime.baseSalary?.currency,
+                          value: x.OffersFullTime.baseSalary?.value,
                         },
                       },
                       bonus: {
                         create: {
-                          currency: x.job.bonus?.currency,
-                          value: x.job.bonus?.value,
+                          currency: x.OffersFullTime.bonus?.currency,
+                          value: x.OffersFullTime.bonus?.value,
                         },
                       },
-                      level: x.job.level,
-                      specialization: x.job.specialization,
+                      level: x.OffersFullTime.level,
+                      specialization: x.OffersFullTime.specialization,
                       stocks: {
                         create: {
-                          currency: x.job.stocks?.currency,
-                          value: x.job.stocks?.value,
+                          currency: x.OffersFullTime.stocks?.currency,
+                          value: x.OffersFullTime.stocks?.value,
                         },
                       },
-                      title: x.job.title,
+                      title: x.OffersFullTime.title,
                       totalCompensation: {
                         create: {
-                          currency: x.job.totalCompensation?.currency,
-                          value: x.job.totalCompensation?.value,
+                          currency: x.OffersFullTime.totalCompensation?.currency,
+                          value: x.OffersFullTime.totalCompensation?.value,
                         },
                       },
                     },
@@ -426,7 +470,550 @@ export const offersProfileRouter = createRouter()
       }
       // TODO: Throw 401
     },
-  });
-  // .mutation('update', {
+  })
+  .mutation('update', {
+    input: z.object({
+      background: z.object({
+        educations: z.array(education),
+        experiences: z.array(experience),
+        id: z.string().optional(),
+        offersProfileId: z.string().optional(),
+        specificYoes: z.array(
+          z.object({
+            backgroundId: z.string().optional(),
+            domain: z.string(),
+            id: z.string().optional(),
+            yoe: z.number()
+          }),
+        ),
+        totalYoe: z.number(),
+      }),
+      createdAt: z.string().optional(),
+      discussion: z.array(reply),
+      id: z.string(),
+      isEditable: z.boolean().nullish(),
+      offers: z.array(offer),
+      profileName: z.string(),
+      token: z.string(),
+      userId: z.string().nullish()
+    }),
+    async resolve({ ctx, input }) {
+      const profileToUpdate = await ctx.prisma.offersProfile.findFirst({
+        where: {
+          id: input.id,
+        },
+      });
+      const profileEditToken = profileToUpdate?.editToken;
+
+      if (profileEditToken === input.token) {
+        await ctx.prisma.offersProfile.update({
+          data: {
+            profileName: input.profileName,
+          },
+          where: {
+            id: input.id,
+          }
+        });
+
+        await ctx.prisma.offersBackground.update({
+          data: {
+            totalYoe: input.background.totalYoe
+          },
+          where: {
+            id: input.background.id
+          }
+        })
+
+        for (const edu of input.background.educations) {
+          if (edu.id) {
+            await ctx.prisma.offersEducation.update({
+              data: {
+                endDate: edu.endDate,
+                field: edu.field,
+                school: edu.school,
+                startDate: edu.startDate,
+                type: edu.type,
+              },
+              where: {
+                id: edu.id
+              }
+            })
+          } else {
+            await ctx.prisma.offersBackground.update({
+              data: {
+                educations: {
+                  create:
+                  {
+                    endDate: edu.endDate,
+                    field: edu.field,
+                    school: edu.school,
+                    startDate: edu.startDate,
+                    type: edu.type,
+                  }
+                }
+              },
+              where: {
+                id: input.background.id
+              }
+            })
+          }
+        }
+
+        for (const exp of input.background.experiences) {
+          if (exp.id) {
+            await ctx.prisma.offersExperience.update({
+              data: {
+                companyId: exp.companyId,
+                durationInMonths: exp.durationInMonths,
+                level: exp.level,
+                specialization: exp.specialization,
+              },
+              where: {
+                id: exp.id
+              }
+            })
+
+            if (exp.monthlySalary) {
+              await ctx.prisma.offersCurrency.update({
+                data: {
+                  currency: exp.monthlySalary.currency,
+                  value: exp.monthlySalary.value,
+                },
+                where: {
+                  id: exp.monthlySalary.id
+                }
+              })
+            }
+
+            if (exp.totalCompensation) {
+              await ctx.prisma.offersCurrency.update({
+                data: {
+                  currency: exp.totalCompensation.currency,
+                  value: exp.totalCompensation.value,
+                },
+                where: {
+                  id: exp.totalCompensation.id
+                }
+              })
+            }
+          } else if (!exp.id) {
+            if (exp.jobType === 'FULLTIME' && exp.totalCompensation?.currency !== undefined && exp.totalCompensation.value !== undefined) {
+              if (exp.companyId) {
+                await ctx.prisma.offersBackground.update({
+                  data: {
+                    experiences: {
+                      create: {
+                        company: {
+                          connect: {
+                            id: exp.companyId,
+                          },
+                        },
+                        durationInMonths: exp.durationInMonths,
+                        jobType: exp.jobType,
+                        level: exp.level,
+                        specialization: exp.specialization,
+                        title: exp.title,
+                        totalCompensation: {
+                          create: {
+                            currency: exp.totalCompensation?.currency,
+                            value: exp.totalCompensation?.value,
+                          },
+                        },
+                      },
+                    }
+                  },
+                  where: {
+                    id: input.background.id
+                  }
+                })
+              } else {
+                await ctx.prisma.offersBackground.update({
+                  data: {
+                    experiences: {
+                      create: {
+                        durationInMonths: exp.durationInMonths,
+                        jobType: exp.jobType,
+                        level: exp.level,
+                        specialization: exp.specialization,
+                        title: exp.title,
+                        totalCompensation: {
+                          create: {
+                            currency: exp.totalCompensation?.currency,
+                            value: exp.totalCompensation?.value,
+                          },
+                        },
+                      }
+                    }
+                  },
+                  where: {
+                    id: input.background.id
+                  }
+                })
+              }
+            }
+            else if (
+              exp.jobType === 'INTERN' &&
+              exp.monthlySalary?.currency !== undefined &&
+              exp.monthlySalary.value !== undefined
+            ) {
+              if (exp.companyId) {
+                await ctx.prisma.offersBackground.update({
+                  data: {
+                    experiences: {
+                      create: {
+                        company: {
+                          connect: {
+                            id: exp.companyId,
+                          },
+                        },
+                        durationInMonths: exp.durationInMonths,
+                        jobType: exp.jobType,
+                        monthlySalary: {
+                          create: {
+                            currency: exp.monthlySalary?.currency,
+                            value: exp.monthlySalary?.value,
+                          },
+                        },
+                        specialization: exp.specialization,
+                        title: exp.title,
+                      }
+                    }
+                  },
+                  where: {
+                    id: input.background.id
+                  }
+                })
+              } else {
+                await ctx.prisma.offersBackground.update({
+                  data: {
+                    experiences: {
+                      create: {
+                        durationInMonths: exp.durationInMonths,
+                        jobType: exp.jobType,
+                        monthlySalary: {
+                          create: {
+                            currency: exp.monthlySalary?.currency,
+                            value: exp.monthlySalary?.value,
+                          },
+                        },
+                        specialization: exp.specialization,
+                        title: exp.title,
+                      }
+                    }
+                  },
+                  where: {
+                    id: input.background.id
+                  }
+                })
+              }
+            }
+          }
+
+        }
+
+        for (const yoe of input.background.specificYoes) {
+          if (yoe.id) {
+            await ctx.prisma.offersSpecificYoe.update({
+              data: {
+                ...yoe
+              },
+              where: {
+                id: yoe.id
+              }
+            })
+          } else {
+            await ctx.prisma.offersBackground.update({
+              data: {
+                specificYoes: {
+                  create:
+                  {
+                    domain: yoe.domain,
+                    yoe: yoe.yoe,
+                  }
+                }
+              },
+              where: {
+                id: input.background.id
+              }
+            })
+          }
+        }
+
+        for (const offerToUpdate of input.offers) {
+          if (offerToUpdate.id) {
+            await ctx.prisma.offersOffer.update({
+              data: {
+                comments: offerToUpdate.comments,
+                companyId: offerToUpdate.companyId,
+                location: offerToUpdate.location,
+                monthYearReceived: offerToUpdate.monthYearReceived,
+                negotiationStrategy: offerToUpdate.negotiationStrategy,
+              },
+              where: {
+                id: offerToUpdate.id
+              }
+            })
+
+            if (offerToUpdate.jobType === "INTERN" || offerToUpdate.jobType === "FULLTIME") {
+              await ctx.prisma.offersOffer.update({
+                data: {
+                  jobType: offerToUpdate.jobType
+                },
+                where: {
+                  id: offerToUpdate.id
+                }
+              })
+            }
+
+            if (offerToUpdate.OffersIntern?.monthlySalary) {
+              await ctx.prisma.offersIntern.update({
+                data: {
+                  internshipCycle: offerToUpdate.OffersIntern.internshipCycle ?? undefined,
+                  specialization: offerToUpdate.OffersIntern.specialization,
+                  startYear: offerToUpdate.OffersIntern.startYear ?? undefined,
+                  title: offerToUpdate.OffersIntern.title,
+                },
+                where: {
+                  id: offerToUpdate.OffersIntern.id,
+                }
+              })
+              await ctx.prisma.offersCurrency.update({
+                data: {
+                  currency: offerToUpdate.OffersIntern.monthlySalary.currency,
+                  value: offerToUpdate.OffersIntern.monthlySalary.value
+                },
+                where: {
+                  id: offerToUpdate.OffersIntern.monthlySalary.id
+                }
+              })
+            }
+
+            if (offerToUpdate.OffersFullTime?.totalCompensation) {
+              await ctx.prisma.offersFullTime.update({
+                data: {
+                  level: offerToUpdate.OffersFullTime.level ?? undefined,
+                  specialization: offerToUpdate.OffersFullTime.specialization,
+                  title: offerToUpdate.OffersFullTime.title,
+                },
+                where: {
+                  id: offerToUpdate.OffersFullTime.id,
+                }
+              })
+              if (offerToUpdate.OffersFullTime.baseSalary) {
+                await ctx.prisma.offersCurrency.update({
+                  data: {
+                    currency: offerToUpdate.OffersFullTime.baseSalary.currency,
+                    value: offerToUpdate.OffersFullTime.baseSalary.value
+                  },
+                  where: {
+                    id: offerToUpdate.OffersFullTime.baseSalary.id
+                  }
+                })
+              }
+              if (offerToUpdate.OffersFullTime.bonus) {
+                await ctx.prisma.offersCurrency.update({
+                  data: {
+                    currency: offerToUpdate.OffersFullTime.bonus.currency,
+                    value: offerToUpdate.OffersFullTime.bonus.value
+                  },
+                  where: {
+                    id: offerToUpdate.OffersFullTime.bonus.id
+                  }
+                })
+              }
+              if (offerToUpdate.OffersFullTime.stocks) {
+                await ctx.prisma.offersCurrency.update({
+                  data: {
+                    currency: offerToUpdate.OffersFullTime.stocks.currency,
+                    value: offerToUpdate.OffersFullTime.stocks.value
+                  },
+                  where: {
+                    id: offerToUpdate.OffersFullTime.stocks.id
+                  }
+                })
+              }
+              await ctx.prisma.offersCurrency.update({
+                data: {
+                  currency: offerToUpdate.OffersFullTime.totalCompensation.currency,
+                  value: offerToUpdate.OffersFullTime.totalCompensation.value
+                },
+                where: {
+                  id: offerToUpdate.OffersFullTime.totalCompensation.id
+                }
+              })
+            }
+          } else {
+            if (
+              offerToUpdate.jobType === "INTERN" &&
+              offerToUpdate.OffersIntern &&
+              offerToUpdate.OffersIntern.internshipCycle &&
+              offerToUpdate.OffersIntern.monthlySalary?.currency &&
+              offerToUpdate.OffersIntern.monthlySalary.value &&
+              offerToUpdate.OffersIntern.startYear
+            ) {
+              await ctx.prisma.offersProfile.update({
+                data: {
+                  offers: {
+                    create: {
+                      OffersIntern: {
+                        create: {
+                          internshipCycle: offerToUpdate.OffersIntern.internshipCycle,
+                          monthlySalary: {
+                            create: {
+                              currency: offerToUpdate.OffersIntern.monthlySalary?.currency,
+                              value: offerToUpdate.OffersIntern.monthlySalary?.value,
+                            },
+                          },
+                          specialization: offerToUpdate.OffersIntern.specialization,
+                          startYear: offerToUpdate.OffersIntern.startYear,
+                          title: offerToUpdate.OffersIntern.title,
+                        },
+                      },
+                      comments: offerToUpdate.comments,
+                      company: {
+                        connect: {
+                          id: offerToUpdate.companyId,
+                        },
+                      },
+                      jobType: offerToUpdate.jobType,
+                      location: offerToUpdate.location,
+                      monthYearReceived: offerToUpdate.monthYearReceived,
+                      negotiationStrategy: offerToUpdate.negotiationStrategy,
+                    }
+                  }
+                },
+                where: {
+                  id: input.id,
+                }
+              })
+            }
+            if (
+              offerToUpdate.jobType === 'FULLTIME' &&
+              offerToUpdate.OffersFullTime &&
+              offerToUpdate.OffersFullTime.baseSalary?.currency &&
+              offerToUpdate.OffersFullTime.baseSalary?.value &&
+              offerToUpdate.OffersFullTime.bonus?.currency &&
+              offerToUpdate.OffersFullTime.bonus?.value &&
+              offerToUpdate.OffersFullTime.stocks?.currency &&
+              offerToUpdate.OffersFullTime.stocks?.value &&
+              offerToUpdate.OffersFullTime.totalCompensation?.currency &&
+              offerToUpdate.OffersFullTime.totalCompensation?.value &&
+              offerToUpdate.OffersFullTime.level
+            ) {
+              await ctx.prisma.offersProfile.update({
+                data: {
+                  offers: {
+                    create: {
+                      OffersFullTime: {
+                        create: {
+                          baseSalary: {
+                            create: {
+                              currency: offerToUpdate.OffersFullTime.baseSalary?.currency,
+                              value: offerToUpdate.OffersFullTime.baseSalary?.value,
+                            },
+                          },
+                          bonus: {
+                            create: {
+                              currency: offerToUpdate.OffersFullTime.bonus?.currency,
+                              value: offerToUpdate.OffersFullTime.bonus?.value,
+                            },
+                          },
+                          level: offerToUpdate.OffersFullTime.level,
+                          specialization: offerToUpdate.OffersFullTime.specialization,
+                          stocks: {
+                            create: {
+                              currency: offerToUpdate.OffersFullTime.stocks?.currency,
+                              value: offerToUpdate.OffersFullTime.stocks?.value,
+                            },
+                          },
+                          title: offerToUpdate.OffersFullTime.title,
+                          totalCompensation: {
+                            create: {
+                              currency: offerToUpdate.OffersFullTime.totalCompensation?.currency,
+                              value: offerToUpdate.OffersFullTime.totalCompensation?.value,
+                            },
+                          },
+                        },
+                      },
+                      comments: offerToUpdate.comments,
+                      company: {
+                        connect: {
+                          id: offerToUpdate.companyId,
+                        },
+                      },
+                      jobType: offerToUpdate.jobType,
+                      location: offerToUpdate.location,
+                      monthYearReceived: offerToUpdate.monthYearReceived,
+                      negotiationStrategy: offerToUpdate.negotiationStrategy,
+                    }
+                  }
+                },
+                where: {
+                  id: input.id,
+                }
+              })
+            }
+          }
+        }
+        // TODO: add analysis to profile object then return
+        const result = await ctx.prisma.offersProfile.findFirst({
+          include: {
+            background: {
+              include: {
+                educations: true,
+                experiences: {
+                  include: {
+                    company: true,
+                    monthlySalary: true,
+                    totalCompensation: true,
+                  },
+                },
+                specificYoes: true,
+              },
+            },
+            discussion: {
+              include: {
+                replies: true,
+                replyingTo: true,
+              },
+            },
+            offers: {
+              include: {
+                OffersFullTime: {
+                  include: {
+                    baseSalary: true,
+                    bonus: true,
+                    stocks: true,
+                    totalCompensation: true,
+                  },
+                },
+                OffersIntern: {
+                  include: {
+                    monthlySalary: true,
+                  },
+                },
+                company: true,
+              },
+            },
+          },
+          where: {
+            id: input.id,
+          },
+        });
+
+        if (result) {
+          return exclude(computeIsEditable(result, input.token), 'editToken')
+        }
+
+        throw new trpc.TRPCError({
+          code: 'NOT_FOUND',
+          message: 'Profile does not exist',
+        });
+      }
 
-  // });
+      throw new trpc.TRPCError({
+        code: 'UNAUTHORIZED',
+        message: 'Invalid token.',
+      });
+    },
+  });