diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..7c2fd46d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,44 @@ +# Copied from https://github.com/facebook/docusaurus/blob/main/.github/workflows/lint.yml +name: Lint + +on: + pull_request: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +env: + DATABASE_URL: 'postgresql://postgres:password@localhost:5432/postgres' + GITHUB_CLIENT_ID: '1234' + GITHUB_CLIENT_SECRET: 'abcd' + NEXTAUTH_SECRET: 'efgh' + NEXTAUTH_URL: 'http://localhost:3000' + NODE_ENV: test + SUPABASE_ANON_KEY: 'ijkl' + SUPABASE_URL: 'https://abcd.supabase.co' + +jobs: + lint: + name: Lint + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '16' + cache: yarn + - name: Installation + run: yarn + - name: Check immutable yarn.lock + run: git diff --exit-code + - name: Lint + run: yarn lint diff --git a/.github/workflows/tsc.yml b/.github/workflows/tsc.yml new file mode 100644 index 00000000..784c4d76 --- /dev/null +++ b/.github/workflows/tsc.yml @@ -0,0 +1,37 @@ +# Copied from https://github.com/facebook/docusaurus/blob/main/.github/workflows/lint.yml +name: Typecheck + +on: + pull_request: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + tsc: + name: Typecheck + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '16' + cache: yarn + - name: Installation + run: yarn + - name: Check immutable yarn.lock + run: git diff --exit-code + # Build the shared types in dependent packages. + - name: Build dependencies + run: yarn turbo run build --filter=ui + - name: Typecheck + run: yarn tsc diff --git a/apps/portal/package.json b/apps/portal/package.json index 88ad7dfd..f1bdb9e7 100644 --- a/apps/portal/package.json +++ b/apps/portal/package.json @@ -30,6 +30,7 @@ "next-auth": "~4.10.3", "react": "18.2.0", "react-dom": "18.2.0", + "react-dropzone": "^14.2.3", "react-hook-form": "^7.36.1", "react-pdf": "^5.7.2", "react-query": "^3.39.2", diff --git a/apps/portal/prisma/migrations/20221011042156_/migration.sql b/apps/portal/prisma/migrations/20221011042156_/migration.sql new file mode 100644 index 00000000..07cf1b58 --- /dev/null +++ b/apps/portal/prisma/migrations/20221011042156_/migration.sql @@ -0,0 +1,120 @@ +/* + Warnings: + + - You are about to drop the column `isAttending` on the `OffersEducation` table. All the data in the column will be lost. + - The primary key for the `OffersFullTime` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `offerId` on the `OffersFullTime` table. All the data in the column will be lost. + - The primary key for the `OffersIntern` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `offerId` on the `OffersIntern` table. All the data in the column will be lost. + - A unique constraint covering the columns `[offersInternId]` on the table `OffersOffer` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[offersFullTimeId]` on the table `OffersOffer` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[profileName]` on the table `OffersProfile` will be added. If there are existing duplicate values, this will fail. + - The required column `id` was added to the `OffersFullTime` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required. + - The required column `id` was added to the `OffersIntern` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required. + +*/ +-- DropForeignKey +ALTER TABLE "OffersBackground" DROP CONSTRAINT "OffersBackground_offersProfileId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersEducation" DROP CONSTRAINT "OffersEducation_backgroundId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersExperience" DROP CONSTRAINT "OffersExperience_backgroundId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersFullTime" DROP CONSTRAINT "OffersFullTime_baseSalaryId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersFullTime" DROP CONSTRAINT "OffersFullTime_bonusId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersFullTime" DROP CONSTRAINT "OffersFullTime_offerId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersFullTime" DROP CONSTRAINT "OffersFullTime_stocksId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersFullTime" DROP CONSTRAINT "OffersFullTime_totalCompensationId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersIntern" DROP CONSTRAINT "OffersIntern_monthlySalaryId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersIntern" DROP CONSTRAINT "OffersIntern_offerId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersOffer" DROP CONSTRAINT "OffersOffer_profileId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersReply" DROP CONSTRAINT "OffersReply_profileId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersSpecificYoe" DROP CONSTRAINT "OffersSpecificYoe_backgroundId_fkey"; + +-- AlterTable +ALTER TABLE "OffersEducation" DROP COLUMN "isAttending"; + +-- AlterTable +ALTER TABLE "OffersFullTime" DROP CONSTRAINT "OffersFullTime_pkey", +DROP COLUMN "offerId", +ADD COLUMN "id" TEXT NOT NULL, +ADD CONSTRAINT "OffersFullTime_pkey" PRIMARY KEY ("id"); + +-- AlterTable +ALTER TABLE "OffersIntern" DROP CONSTRAINT "OffersIntern_pkey", +DROP COLUMN "offerId", +ADD COLUMN "id" TEXT NOT NULL, +ADD CONSTRAINT "OffersIntern_pkey" PRIMARY KEY ("id"); + +-- AlterTable +ALTER TABLE "OffersOffer" ADD COLUMN "offersFullTimeId" TEXT, +ADD COLUMN "offersInternId" TEXT; + +-- CreateIndex +CREATE UNIQUE INDEX "OffersOffer_offersInternId_key" ON "OffersOffer"("offersInternId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OffersOffer_offersFullTimeId_key" ON "OffersOffer"("offersFullTimeId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OffersProfile_profileName_key" ON "OffersProfile"("profileName"); + +-- AddForeignKey +ALTER TABLE "OffersBackground" ADD CONSTRAINT "OffersBackground_offersProfileId_fkey" FOREIGN KEY ("offersProfileId") REFERENCES "OffersProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersSpecificYoe" ADD CONSTRAINT "OffersSpecificYoe_backgroundId_fkey" FOREIGN KEY ("backgroundId") REFERENCES "OffersBackground"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersExperience" ADD CONSTRAINT "OffersExperience_backgroundId_fkey" FOREIGN KEY ("backgroundId") REFERENCES "OffersBackground"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersEducation" ADD CONSTRAINT "OffersEducation_backgroundId_fkey" FOREIGN KEY ("backgroundId") REFERENCES "OffersBackground"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersReply" ADD CONSTRAINT "OffersReply_profileId_fkey" FOREIGN KEY ("profileId") REFERENCES "OffersProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersOffer" ADD CONSTRAINT "OffersOffer_profileId_fkey" FOREIGN KEY ("profileId") REFERENCES "OffersProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersOffer" ADD CONSTRAINT "OffersOffer_offersInternId_fkey" FOREIGN KEY ("offersInternId") REFERENCES "OffersIntern"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersOffer" ADD CONSTRAINT "OffersOffer_offersFullTimeId_fkey" FOREIGN KEY ("offersFullTimeId") REFERENCES "OffersFullTime"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersIntern" ADD CONSTRAINT "OffersIntern_monthlySalaryId_fkey" FOREIGN KEY ("monthlySalaryId") REFERENCES "OffersCurrency"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersFullTime" ADD CONSTRAINT "OffersFullTime_totalCompensationId_fkey" FOREIGN KEY ("totalCompensationId") REFERENCES "OffersCurrency"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersFullTime" ADD CONSTRAINT "OffersFullTime_baseSalaryId_fkey" FOREIGN KEY ("baseSalaryId") REFERENCES "OffersCurrency"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersFullTime" ADD CONSTRAINT "OffersFullTime_bonusId_fkey" FOREIGN KEY ("bonusId") REFERENCES "OffersCurrency"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersFullTime" ADD CONSTRAINT "OffersFullTime_stocksId_fkey" FOREIGN KEY ("stocksId") REFERENCES "OffersCurrency"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/portal/prisma/migrations/20221012161857_add_user_to_replies/migration.sql b/apps/portal/prisma/migrations/20221012161857_add_user_to_replies/migration.sql new file mode 100644 index 00000000..bc51e8e1 --- /dev/null +++ b/apps/portal/prisma/migrations/20221012161857_add_user_to_replies/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `creator` on the `OffersReply` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "OffersReply" DROP COLUMN "creator", +ADD COLUMN "userId" TEXT; + +-- AddForeignKey +ALTER TABLE "OffersReply" ADD CONSTRAINT "OffersReply_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/portal/prisma/migrations/20221013032033_update_resume_vote_to_enum/migration.sql b/apps/portal/prisma/migrations/20221013032033_update_resume_vote_to_enum/migration.sql new file mode 100644 index 00000000..935df922 --- /dev/null +++ b/apps/portal/prisma/migrations/20221013032033_update_resume_vote_to_enum/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - Changed the type of `value` on the `ResumesCommentVote` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + +*/ +-- AlterTable +ALTER TABLE "ResumesCommentVote" DROP COLUMN "value", +ADD COLUMN "value" "Vote" NOT NULL; diff --git a/apps/portal/prisma/migrations/20221014192315_/migration.sql b/apps/portal/prisma/migrations/20221014192315_/migration.sql new file mode 100644 index 00000000..20352390 --- /dev/null +++ b/apps/portal/prisma/migrations/20221014192315_/migration.sql @@ -0,0 +1,60 @@ +-- CreateTable +CREATE TABLE "OffersAnalysis" ( + "id" TEXT NOT NULL, + "profileId" TEXT NOT NULL, + "offerId" TEXT NOT NULL, + "overallPercentile" INTEGER NOT NULL, + "noOfSimilarOffers" INTEGER NOT NULL, + "companyPercentile" INTEGER NOT NULL, + "noOfSimilarCompanyOffers" INTEGER NOT NULL, + + CONSTRAINT "OffersAnalysis_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_TopOverallOffers" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_TopCompanyOffers" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "OffersAnalysis_profileId_key" ON "OffersAnalysis"("profileId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OffersAnalysis_offerId_key" ON "OffersAnalysis"("offerId"); + +-- CreateIndex +CREATE UNIQUE INDEX "_TopOverallOffers_AB_unique" ON "_TopOverallOffers"("A", "B"); + +-- CreateIndex +CREATE INDEX "_TopOverallOffers_B_index" ON "_TopOverallOffers"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_TopCompanyOffers_AB_unique" ON "_TopCompanyOffers"("A", "B"); + +-- CreateIndex +CREATE INDEX "_TopCompanyOffers_B_index" ON "_TopCompanyOffers"("B"); + +-- AddForeignKey +ALTER TABLE "OffersAnalysis" ADD CONSTRAINT "OffersAnalysis_profileId_fkey" FOREIGN KEY ("profileId") REFERENCES "OffersProfile"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersAnalysis" ADD CONSTRAINT "OffersAnalysis_offerId_fkey" FOREIGN KEY ("offerId") REFERENCES "OffersOffer"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TopOverallOffers" ADD CONSTRAINT "_TopOverallOffers_A_fkey" FOREIGN KEY ("A") REFERENCES "OffersAnalysis"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TopOverallOffers" ADD CONSTRAINT "_TopOverallOffers_B_fkey" FOREIGN KEY ("B") REFERENCES "OffersOffer"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TopCompanyOffers" ADD CONSTRAINT "_TopCompanyOffers_A_fkey" FOREIGN KEY ("A") REFERENCES "OffersAnalysis"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_TopCompanyOffers" ADD CONSTRAINT "_TopCompanyOffers_B_fkey" FOREIGN KEY ("B") REFERENCES "OffersOffer"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/portal/prisma/migrations/20221014205230_/migration.sql b/apps/portal/prisma/migrations/20221014205230_/migration.sql new file mode 100644 index 00000000..aec827dc --- /dev/null +++ b/apps/portal/prisma/migrations/20221014205230_/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "OffersAnalysis" ALTER COLUMN "overallPercentile" SET DATA TYPE DOUBLE PRECISION, +ALTER COLUMN "companyPercentile" SET DATA TYPE DOUBLE PRECISION; diff --git a/apps/portal/prisma/migrations/20221014211740_/migration.sql b/apps/portal/prisma/migrations/20221014211740_/migration.sql new file mode 100644 index 00000000..1c960010 --- /dev/null +++ b/apps/portal/prisma/migrations/20221014211740_/migration.sql @@ -0,0 +1,11 @@ +-- DropForeignKey +ALTER TABLE "OffersAnalysis" DROP CONSTRAINT "OffersAnalysis_offerId_fkey"; + +-- DropForeignKey +ALTER TABLE "OffersAnalysis" DROP CONSTRAINT "OffersAnalysis_profileId_fkey"; + +-- AddForeignKey +ALTER TABLE "OffersAnalysis" ADD CONSTRAINT "OffersAnalysis_profileId_fkey" FOREIGN KEY ("profileId") REFERENCES "OffersProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OffersAnalysis" ADD CONSTRAINT "OffersAnalysis_offerId_fkey" FOREIGN KEY ("offerId") REFERENCES "OffersOffer"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/portal/prisma/schema.prisma b/apps/portal/prisma/schema.prisma index b6a65a12..45a730a3 100644 --- a/apps/portal/prisma/schema.prisma +++ b/apps/portal/prisma/schema.prisma @@ -1,92 +1,93 @@ // Refer to the Prisma schema docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" } datasource db { - provider = "postgresql" - url = env("DATABASE_URL") + provider = "postgresql" + url = env("DATABASE_URL") } // Necessary for NextAuth. model Account { - id String @id @default(cuid()) - userId String - type String - provider String - providerAccountId String - refresh_token String? @db.Text - access_token String? @db.Text - expires_at Int? - token_type String? - scope String? - id_token String? @db.Text - session_state String? - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([provider, providerAccountId]) + id String @id @default(cuid()) + userId String + type String + provider String + providerAccountId String + refresh_token String? @db.Text + access_token String? @db.Text + expires_at Int? + token_type String? + scope String? + id_token String? @db.Text + session_state String? + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([provider, providerAccountId]) } model Session { - id String @id @default(cuid()) - sessionToken String @unique - userId String - expires DateTime - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + sessionToken String @unique + userId String + expires DateTime + user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model User { - id String @id @default(cuid()) - name String? - email String? @unique - emailVerified DateTime? - image String? - accounts Account[] - sessions Session[] - todos Todo[] - resumesResumes ResumesResume[] - resumesStars ResumesStar[] - resumesComments ResumesComment[] - resumesCommentVotes ResumesCommentVote[] - questionsQuestions QuestionsQuestion[] - questionsQuestionEncounters QuestionsQuestionEncounter[] - questionsQuestionVotes QuestionsQuestionVote[] - questionsQuestionComments QuestionsQuestionComment[] - questionsQuestionCommentVotes QuestionsQuestionCommentVote[] - questionsAnswers QuestionsAnswer[] - questionsAnswerVotes QuestionsAnswerVote[] - questionsAnswerComments QuestionsAnswerComment[] - questionsAnswerCommentVotes QuestionsAnswerCommentVote[] - OffersProfile OffersProfile[] + id String @id @default(cuid()) + name String? + email String? @unique + emailVerified DateTime? + image String? + accounts Account[] + sessions Session[] + todos Todo[] + resumesResumes ResumesResume[] + resumesStars ResumesStar[] + resumesComments ResumesComment[] + resumesCommentVotes ResumesCommentVote[] + questionsQuestions QuestionsQuestion[] + questionsQuestionEncounters QuestionsQuestionEncounter[] + questionsQuestionVotes QuestionsQuestionVote[] + questionsQuestionComments QuestionsQuestionComment[] + questionsQuestionCommentVotes QuestionsQuestionCommentVote[] + questionsAnswers QuestionsAnswer[] + questionsAnswerVotes QuestionsAnswerVote[] + questionsAnswerComments QuestionsAnswerComment[] + questionsAnswerCommentVotes QuestionsAnswerCommentVote[] + OffersProfile OffersProfile[] + offersDiscussion OffersReply[] } enum Vote { - UPVOTE - DOWNVOTE + UPVOTE + DOWNVOTE } model VerificationToken { - identifier String - token String @unique - expires DateTime + identifier String + token String @unique + expires DateTime - @@unique([identifier, token]) + @@unique([identifier, token]) } model Todo { - id String @id @default(cuid()) - userId String - text String @db.Text - status TodoStatus @default(INCOMPLETE) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + userId String + text String @db.Text + status TodoStatus @default(INCOMPLETE) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id], onDelete: Cascade) } enum TodoStatus { - INCOMPLETE - COMPLETE + INCOMPLETE + COMPLETE } model Company { @@ -108,65 +109,65 @@ model Company { // use camelCase for field names, and try to name them consistently // across all models in this file. model ResumesResume { - id String @id @default(cuid()) - userId String - title String @db.Text - // TODO: Update role, experience, location to use Enums - role String @db.Text - experience String @db.Text - location String @db.Text - url String - additionalInfo String? @db.Text - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - stars ResumesStar[] - comments ResumesComment[] + id String @id @default(cuid()) + userId String + title String @db.Text + // TODO: Update role, experience, location to use Enums + role String @db.Text + experience String @db.Text + location String @db.Text + url String + additionalInfo String? @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + stars ResumesStar[] + comments ResumesComment[] } model ResumesStar { - id String @id @default(cuid()) - userId String - resumeId String - createdAt DateTime @default(now()) - resume ResumesResume @relation(fields: [resumeId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + userId String + resumeId String + createdAt DateTime @default(now()) + resume ResumesResume @relation(fields: [resumeId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) - @@unique([userId, resumeId]) + @@unique([userId, resumeId]) } model ResumesComment { - id String @id @default(cuid()) - userId String - resumeId String - description String @db.Text - section ResumesSection - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - resume ResumesResume @relation(fields: [resumeId], references: [id], onDelete: Cascade) - votes ResumesCommentVote[] - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + userId String + resumeId String + description String @db.Text + section ResumesSection + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + resume ResumesResume @relation(fields: [resumeId], references: [id], onDelete: Cascade) + votes ResumesCommentVote[] + user User @relation(fields: [userId], references: [id], onDelete: Cascade) } enum ResumesSection { - GENERAL - EDUCATION - EXPERIENCE - PROJECTS - SKILLS + GENERAL + EDUCATION + EXPERIENCE + PROJECTS + SKILLS } model ResumesCommentVote { - id String @id @default(cuid()) - userId String - commentId String - value Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - comment ResumesComment @relation(fields: [commentId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + userId String + commentId String + value Vote + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment ResumesComment @relation(fields: [commentId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) - @@unique([userId, commentId]) + @@unique([userId, commentId]) } // End of Resumes project models. @@ -177,175 +178,202 @@ model ResumesCommentVote { // across all models in this file. model OffersProfile { - id String @id @default(cuid()) - profileName String @unique - createdAt DateTime @default(now()) + id String @id @default(cuid()) + profileName String @unique + createdAt DateTime @default(now()) - background OffersBackground? + background OffersBackground? - editToken String + editToken String - discussion OffersReply[] + discussion OffersReply[] - offers OffersOffer[] + offers OffersOffer[] - user User? @relation(fields: [userId], references: [id]) - userId String? + user User? @relation(fields: [userId], references: [id]) + userId String? + + analysis OffersAnalysis? } model OffersBackground { - id String @id @default(cuid()) + id String @id @default(cuid()) - totalYoe Int? - specificYoes OffersSpecificYoe[] + totalYoe Int + specificYoes OffersSpecificYoe[] - experiences OffersExperience[] // For extensibility in the future + experiences OffersExperience[] // For extensibility in the future - educations OffersEducation[] // For extensibility in the future + educations OffersEducation[] // For extensibility in the future - profile OffersProfile @relation(fields: [offersProfileId], references: [id]) - offersProfileId String @unique + profile OffersProfile @relation(fields: [offersProfileId], references: [id], onDelete: Cascade) + offersProfileId String @unique } model OffersSpecificYoe { - id String @id @default(cuid()) + id String @id @default(cuid()) - yoe Int - domain String + yoe Int + domain String - background OffersBackground @relation(fields: [backgroundId], references: [id]) - backgroundId String + background OffersBackground @relation(fields: [backgroundId], references: [id], onDelete: Cascade) + backgroundId String } model OffersExperience { - id String @id @default(cuid()) + id String @id @default(cuid()) - company Company? @relation(fields: [companyId], references: [id]) - companyId String? + company Company? @relation(fields: [companyId], references: [id]) + companyId String? - jobType JobType? - title String? + jobType JobType? + title String? - // Add more fields - durationInMonths Int? - specialization String? + // Add more fields + durationInMonths Int? + specialization String? - // FULLTIME fields - level String? - totalCompensation OffersCurrency? @relation("ExperienceTotalCompensation", fields: [totalCompensationId], references: [id]) - totalCompensationId String? @unique + // FULLTIME fields + level String? + totalCompensation OffersCurrency? @relation("ExperienceTotalCompensation", fields: [totalCompensationId], references: [id]) + totalCompensationId String? @unique - // INTERN fields - monthlySalary OffersCurrency? @relation("ExperienceMonthlySalary", fields: [monthlySalaryId], references: [id]) - monthlySalaryId String? @unique + // INTERN fields + monthlySalary OffersCurrency? @relation("ExperienceMonthlySalary", fields: [monthlySalaryId], references: [id]) + monthlySalaryId String? @unique - background OffersBackground @relation(fields: [backgroundId], references: [id]) - backgroundId String + background OffersBackground @relation(fields: [backgroundId], references: [id], onDelete: Cascade) + backgroundId String } model OffersCurrency { - id String @id @default(cuid()) - value Int - currency String + id String @id @default(cuid()) + value Int + currency String - // Experience - OffersExperienceTotalCompensation OffersExperience? @relation("ExperienceTotalCompensation") - OffersExperienceMonthlySalary OffersExperience? @relation("ExperienceMonthlySalary") + // Experience + OffersExperienceTotalCompensation OffersExperience? @relation("ExperienceTotalCompensation") + OffersExperienceMonthlySalary OffersExperience? @relation("ExperienceMonthlySalary") - // Full Time - OffersTotalCompensation OffersFullTime? @relation("OfferTotalCompensation") - OffersBaseSalary OffersFullTime? @relation("OfferBaseSalary") - OffersBonus OffersFullTime? @relation("OfferBonus") - OffersStocks OffersFullTime? @relation("OfferStocks") + // Full Time + OffersTotalCompensation OffersFullTime? @relation("OfferTotalCompensation") + OffersBaseSalary OffersFullTime? @relation("OfferBaseSalary") + OffersBonus OffersFullTime? @relation("OfferBonus") + OffersStocks OffersFullTime? @relation("OfferStocks") - // Intern - OffersMonthlySalary OffersIntern? + // Intern + OffersMonthlySalary OffersIntern? } enum JobType { - INTERN - FULLTIME + INTERN + FULLTIME } model OffersEducation { - id String @id @default(cuid()) - type String? - field String? + id String @id @default(cuid()) + type String? + field String? - // Add more fields - school String? - startDate DateTime? - endDate DateTime? + school String? + startDate DateTime? + endDate DateTime? - background OffersBackground @relation(fields: [backgroundId], references: [id]) - backgroundId String + background OffersBackground @relation(fields: [backgroundId], references: [id], onDelete: Cascade) + backgroundId String } model OffersReply { - id String @id @default(cuid()) - creator String - createdAt DateTime @default(now()) - message String + id String @id @default(cuid()) + createdAt DateTime @default(now()) + message String + + replyingToId String? + replyingTo OffersReply? @relation("ReplyThread", fields: [replyingToId], references: [id]) + replies OffersReply[] @relation("ReplyThread") - replyingToId String? - replyingTo OffersReply? @relation("ReplyThread", fields: [replyingToId], references: [id]) - replies OffersReply[] @relation("ReplyThread") + profile OffersProfile @relation(fields: [profileId], references: [id], onDelete: Cascade) + profileId String - profile OffersProfile @relation(fields: [profileId], references: [id]) - profileId String + user User? @relation(fields: [userId], references: [id]) + userId String? } model OffersOffer { - id String @id @default(cuid()) + id String @id @default(cuid()) - profile OffersProfile @relation(fields: [profileId], references: [id]) - profileId String + profile OffersProfile @relation(fields: [profileId], references: [id], onDelete: Cascade) + profileId String - company Company @relation(fields: [companyId], references: [id]) - companyId String + company Company @relation(fields: [companyId], references: [id]) + companyId String - monthYearReceived DateTime - location String - negotiationStrategy String? - comments String? + monthYearReceived DateTime + location String + negotiationStrategy String + comments String - jobType JobType + jobType JobType - OffersIntern OffersIntern? @relation(fields: [offersInternId], references: [id]) - offersInternId String? @unique + OffersIntern OffersIntern? @relation(fields: [offersInternId], references: [id], onDelete: Cascade) + offersInternId String? @unique - OffersFullTime OffersFullTime? @relation(fields: [offersFullTimeId], references: [id]) - offersFullTimeId String? @unique + OffersFullTime OffersFullTime? @relation(fields: [offersFullTimeId], references: [id], onDelete: Cascade) + offersFullTimeId String? @unique + + OffersAnalysis OffersAnalysis? @relation("HighestOverallOffer") + OffersAnalysisTopOverallOffers OffersAnalysis[] @relation("TopOverallOffers") + OffersAnalysisTopCompanyOffers OffersAnalysis[] @relation("TopCompanyOffers") } model OffersIntern { - id String @id @default(cuid()) + id String @id @default(cuid()) - title String - specialization String - internshipCycle String - startYear Int - monthlySalary OffersCurrency @relation(fields: [monthlySalaryId], references: [id]) - monthlySalaryId String @unique + title String + specialization String + internshipCycle String + startYear Int + monthlySalary OffersCurrency @relation(fields: [monthlySalaryId], references: [id], onDelete: Cascade) + monthlySalaryId String @unique - OffersOffer OffersOffer? + OffersOffer OffersOffer? } model OffersFullTime { - id String @id @default(cuid()) - title String - specialization String - level String - totalCompensation OffersCurrency @relation("OfferTotalCompensation", fields: [totalCompensationId], references: [id]) - totalCompensationId String @unique - baseSalary OffersCurrency @relation("OfferBaseSalary", fields: [baseSalaryId], references: [id]) - baseSalaryId String @unique - bonus OffersCurrency @relation("OfferBonus", fields: [bonusId], references: [id]) - bonusId String @unique - stocks OffersCurrency @relation("OfferStocks", fields: [stocksId], references: [id]) - stocksId String @unique - - OffersOffer OffersOffer? + id String @id @default(cuid()) + title String + specialization String + level String + totalCompensation OffersCurrency @relation("OfferTotalCompensation", fields: [totalCompensationId], references: [id], onDelete: Cascade) + totalCompensationId String @unique + baseSalary OffersCurrency @relation("OfferBaseSalary", fields: [baseSalaryId], references: [id], onDelete: Cascade) + baseSalaryId String @unique + bonus OffersCurrency @relation("OfferBonus", fields: [bonusId], references: [id], onDelete: Cascade) + bonusId String @unique + stocks OffersCurrency @relation("OfferStocks", fields: [stocksId], references: [id], onDelete: Cascade) + stocksId String @unique + + OffersOffer OffersOffer? +} + +model OffersAnalysis { + id String @id @default(cuid()) + + profile OffersProfile @relation(fields: [profileId], references: [id], onDelete: Cascade) + profileId String @unique + + overallHighestOffer OffersOffer @relation("HighestOverallOffer", fields: [offerId], references: [id], onDelete: Cascade) + offerId String @unique + + // OVERALL + overallPercentile Float + noOfSimilarOffers Int + topOverallOffers OffersOffer[] @relation("TopOverallOffers") + + // Company + companyPercentile Float + noOfSimilarCompanyOffers Int + topCompanyOffers OffersOffer[] @relation("TopCompanyOffers") } // End of Offers project models. @@ -356,24 +384,24 @@ model OffersFullTime { // across all models in this file. enum QuestionsQuestionType { - CODING - SYSTEM_DESIGN - BEHAVIORAL + CODING + SYSTEM_DESIGN + BEHAVIORAL } model QuestionsQuestion { - id String @id @default(cuid()) - userId String? - content String @db.Text - questionType QuestionsQuestionType - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + userId String? + content String @db.Text + questionType QuestionsQuestionType + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - encounters QuestionsQuestionEncounter[] - votes QuestionsQuestionVote[] - comments QuestionsQuestionComment[] - answers QuestionsAnswer[] + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + encounters QuestionsQuestionEncounter[] + votes QuestionsQuestionVote[] + comments QuestionsQuestionComment[] + answers QuestionsAnswer[] } model QuestionsQuestionEncounter { @@ -394,99 +422,99 @@ model QuestionsQuestionEncounter { } model QuestionsQuestionVote { - id String @id @default(cuid()) - questionId String - userId String? - vote Vote - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + questionId String + userId String? + vote Vote + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) - @@unique([questionId, userId]) + @@unique([questionId, userId]) } model QuestionsQuestionComment { - id String @id @default(cuid()) - questionId String - userId String? - content String @db.Text - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + questionId String + userId String? + content String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) - votes QuestionsQuestionCommentVote[] + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) + votes QuestionsQuestionCommentVote[] } model QuestionsQuestionCommentVote { - id String @id @default(cuid()) - questionCommentId String - userId String? - vote Vote - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + questionCommentId String + userId String? + vote Vote + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - comment QuestionsQuestionComment @relation(fields: [questionCommentId], references: [id], onDelete: Cascade) + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + comment QuestionsQuestionComment @relation(fields: [questionCommentId], references: [id], onDelete: Cascade) - @@unique([questionCommentId, userId]) + @@unique([questionCommentId, userId]) } model QuestionsAnswer { - id String @id @default(cuid()) - questionId String - userId String? - content String @db.Text - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + questionId String + userId String? + content String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) - votes QuestionsAnswerVote[] - comments QuestionsAnswerComment[] + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) + votes QuestionsAnswerVote[] + comments QuestionsAnswerComment[] } model QuestionsAnswerVote { - id String @id @default(cuid()) - answerId String - userId String? - vote Vote - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + answerId String + userId String? + vote Vote + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - answer QuestionsAnswer @relation(fields: [answerId], references: [id], onDelete: Cascade) + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + answer QuestionsAnswer @relation(fields: [answerId], references: [id], onDelete: Cascade) - @@unique([answerId, userId]) + @@unique([answerId, userId]) } model QuestionsAnswerComment { - id String @id @default(cuid()) - answerId String - userId String? - content String @db.Text - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + answerId String + userId String? + content String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - answer QuestionsAnswer @relation(fields: [answerId], references: [id], onDelete: Cascade) - votes QuestionsAnswerCommentVote[] + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + answer QuestionsAnswer @relation(fields: [answerId], references: [id], onDelete: Cascade) + votes QuestionsAnswerCommentVote[] } model QuestionsAnswerCommentVote { - id String @id @default(cuid()) - answerCommentId String - userId String? - vote Vote - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + answerCommentId String + userId String? + vote Vote + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - comment QuestionsAnswerComment @relation(fields: [answerCommentId], references: [id], onDelete: Cascade) + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + comment QuestionsAnswerComment @relation(fields: [answerCommentId], references: [id], onDelete: Cascade) - @@unique([answerCommentId, userId]) + @@unique([answerCommentId, userId]) } // End of Questions project models. diff --git a/apps/portal/public/test_resume.pdf b/apps/portal/public/test_resume.pdf deleted file mode 100644 index 279b6a25..00000000 Binary files a/apps/portal/public/test_resume.pdf and /dev/null differ diff --git a/apps/portal/src/components/global/AppShell.tsx b/apps/portal/src/components/global/AppShell.tsx index 0275dbb5..bcb9af67 100644 --- a/apps/portal/src/components/global/AppShell.tsx +++ b/apps/portal/src/components/global/AppShell.tsx @@ -109,6 +109,7 @@ export default function AppShell({ children }: Props) { navigation: ProductNavigationItems; showGlobalNav: boolean; title: string; + titleHref: string; }> = (() => { const path = router.pathname; if (path.startsWith('/resumes')) { @@ -190,6 +191,7 @@ export default function AppShell({ children }: Props) {
diff --git a/apps/portal/src/components/global/HomeNavigation.ts b/apps/portal/src/components/global/HomeNavigation.ts index 073a7b36..eb41d372 100644 --- a/apps/portal/src/components/global/HomeNavigation.ts +++ b/apps/portal/src/components/global/HomeNavigation.ts @@ -17,6 +17,7 @@ const config = { navigation, showGlobalNav: true, title: 'Tech Interview Handbook', + titleHref: '/', }; export default config; diff --git a/apps/portal/src/components/global/ProductNavigation.tsx b/apps/portal/src/components/global/ProductNavigation.tsx index caae6c08..74e6dada 100644 --- a/apps/portal/src/components/global/ProductNavigation.tsx +++ b/apps/portal/src/components/global/ProductNavigation.tsx @@ -1,13 +1,16 @@ import clsx from 'clsx'; import Link from 'next/link'; +import { useRouter } from 'next/router'; import { Fragment } from 'react'; import { Menu, Transition } from '@headlessui/react'; import { ChevronDownIcon } from '@heroicons/react/20/solid'; +import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'; type NavigationItem = Readonly<{ children?: ReadonlyArray; href: string; name: string; + target?: '_blank'; }>; export type ProductNavigationItems = ReadonlyArray; @@ -15,15 +18,21 @@ export type ProductNavigationItems = ReadonlyArray; type Props = Readonly<{ items: ProductNavigationItems; title: string; + titleHref: string; }>; -export default function ProductNavigation({ items, title }: Props) { +export default function ProductNavigation({ items, title, titleHref }: Props) { + const router = useRouter(); + return ( -