diff --git a/apps/portal/prisma/migrations/20221031033529_change_analysis_models_to_allow_for_multiple_company_analysis/migration.sql b/apps/portal/prisma/migrations/20221031033529_change_analysis_models_to_allow_for_multiple_company_analysis/migration.sql new file mode 100644 index 00000000..f416f406 --- /dev/null +++ b/apps/portal/prisma/migrations/20221031033529_change_analysis_models_to_allow_for_multiple_company_analysis/migration.sql @@ -0,0 +1,113 @@ +/* + Warnings: + + - You are about to drop the column `companyPercentile` on the `OffersAnalysis` table. All the data in the column will be lost. + - You are about to drop the column `noOfSimilarCompanyOffers` on the `OffersAnalysis` table. All the data in the column will be lost. + - You are about to drop the column `noOfSimilarOffers` on the `OffersAnalysis` table. All the data in the column will be lost. + - You are about to drop the column `overallPercentile` on the `OffersAnalysis` table. All the data in the column will be lost. + - You are about to drop the column `userId` on the `OffersProfile` table. All the data in the column will be lost. + - You are about to drop the `_TopCompanyOffers` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `_TopOverallOffers` table. If the table is not empty, all the data it contains will be lost. + - Added the required column `overallAnalysisUnitId` to the `OffersAnalysis` table without a default value. This is not possible if the table is not empty. + - Added the required column `updatedAt` to the `OffersAnalysis` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "OffersProfile" DROP CONSTRAINT "OffersProfile_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "_TopCompanyOffers" DROP CONSTRAINT "_TopCompanyOffers_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_TopCompanyOffers" DROP CONSTRAINT "_TopCompanyOffers_B_fkey"; + +-- DropForeignKey +ALTER TABLE "_TopOverallOffers" DROP CONSTRAINT "_TopOverallOffers_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_TopOverallOffers" DROP CONSTRAINT "_TopOverallOffers_B_fkey"; + +-- AlterTable +ALTER TABLE "OffersAnalysis" DROP COLUMN "companyPercentile", +DROP COLUMN "noOfSimilarCompanyOffers", +DROP COLUMN "noOfSimilarOffers", +DROP COLUMN "overallPercentile", +ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "overallAnalysisUnitId" TEXT NOT NULL, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL; + +-- AlterTable +ALTER TABLE "OffersProfile" DROP COLUMN "userId"; + +-- DropTable +DROP TABLE "_TopCompanyOffers"; + +-- DropTable +DROP TABLE "_TopOverallOffers"; + +-- CreateTable +CREATE TABLE "OffersAnalysisUnit" ( + "id" TEXT NOT NULL, + "companyName" TEXT NOT NULL, + "percentile" DOUBLE PRECISION NOT NULL, + "noOfSimilarOffers" INTEGER NOT NULL, + + CONSTRAINT "OffersAnalysisUnit_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_OffersProfileToUser" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_CompanyAnalysis" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_OffersAnalysisUnitToOffersOffer" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "_OffersProfileToUser_AB_unique" ON "_OffersProfileToUser"("A", "B"); + +-- CreateIndex +CREATE INDEX "_OffersProfileToUser_B_index" ON "_OffersProfileToUser"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_CompanyAnalysis_AB_unique" ON "_CompanyAnalysis"("A", "B"); + +-- CreateIndex +CREATE INDEX "_CompanyAnalysis_B_index" ON "_CompanyAnalysis"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_OffersAnalysisUnitToOffersOffer_AB_unique" ON "_OffersAnalysisUnitToOffersOffer"("A", "B"); + +-- CreateIndex +CREATE INDEX "_OffersAnalysisUnitToOffersOffer_B_index" ON "_OffersAnalysisUnitToOffersOffer"("B"); + +-- AddForeignKey +ALTER TABLE "OffersAnalysis" ADD CONSTRAINT "OffersAnalysis_overallAnalysisUnitId_fkey" FOREIGN KEY ("overallAnalysisUnitId") REFERENCES "OffersAnalysisUnit"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_OffersProfileToUser" ADD CONSTRAINT "_OffersProfileToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "OffersProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_OffersProfileToUser" ADD CONSTRAINT "_OffersProfileToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_CompanyAnalysis" ADD CONSTRAINT "_CompanyAnalysis_A_fkey" FOREIGN KEY ("A") REFERENCES "OffersAnalysis"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_CompanyAnalysis" ADD CONSTRAINT "_CompanyAnalysis_B_fkey" FOREIGN KEY ("B") REFERENCES "OffersAnalysisUnit"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_OffersAnalysisUnitToOffersOffer" ADD CONSTRAINT "_OffersAnalysisUnitToOffersOffer_A_fkey" FOREIGN KEY ("A") REFERENCES "OffersAnalysisUnit"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_OffersAnalysisUnitToOffersOffer" ADD CONSTRAINT "_OffersAnalysisUnitToOffersOffer_B_fkey" FOREIGN KEY ("B") REFERENCES "OffersOffer"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/portal/prisma/schema.prisma b/apps/portal/prisma/schema.prisma index d9c273b7..3a9277f0 100644 --- a/apps/portal/prisma/schema.prisma +++ b/apps/portal/prisma/schema.prisma @@ -225,8 +225,7 @@ model OffersProfile { offers OffersOffer[] - user User? @relation(fields: [userId], references: [id]) - userId String? + users User[] analysis OffersAnalysis? } @@ -362,9 +361,8 @@ model OffersOffer { offersFullTime OffersFullTime? @relation(fields: [offersFullTimeId], references: [id], onDelete: Cascade) offersFullTimeId String? @unique - OffersAnalysis OffersAnalysis? @relation("HighestOverallOffer") - OffersAnalysisTopOverallOffers OffersAnalysis[] @relation("TopOverallOffers") - OffersAnalysisTopCompanyOffers OffersAnalysis[] @relation("TopCompanyOffers") + offersAnalysis OffersAnalysis? @relation("HighestOverallOffer") + offersAnalysisUnit OffersAnalysisUnit[] } model OffersIntern { @@ -396,7 +394,9 @@ model OffersFullTime { } model OffersAnalysis { - id String @id @default(cuid()) + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt profile OffersProfile @relation(fields: [profileId], references: [id], onDelete: Cascade) profileId String @unique @@ -405,14 +405,22 @@ model OffersAnalysis { offerId String @unique // OVERALL - overallPercentile Float + overallAnalysis OffersAnalysisUnit @relation("OverallAnalysis", fields: [overallAnalysisUnitId], references: [id]) + overallAnalysisUnitId String + + companyAnalysis OffersAnalysisUnit[] @relation("CompanyAnalysis") +} + +model OffersAnalysisUnit { + id String @id @default(cuid()) + + companyName String + percentile Float noOfSimilarOffers Int - topOverallOffers OffersOffer[] @relation("TopOverallOffers") + topSimilarOffers OffersOffer[] - // Company - companyPercentile Float - noOfSimilarCompanyOffers Int - topCompanyOffers OffersOffer[] @relation("TopCompanyOffers") + offersAnalysisOverall OffersAnalysis[] @relation("OverallAnalysis") + offersAnalysisCompany OffersAnalysis[] @relation("CompanyAnalysis") } // End of Offers project models. diff --git a/apps/portal/src/components/offers/OffersNavigation.tsx b/apps/portal/src/components/offers/OffersNavigation.tsx index 26719933..315bac9f 100644 --- a/apps/portal/src/components/offers/OffersNavigation.tsx +++ b/apps/portal/src/components/offers/OffersNavigation.tsx @@ -7,7 +7,7 @@ const navigation: ProductNavigationItems = [ const navigationAuthenticated: ProductNavigationItems = [ { href: '/offers/submit', name: 'Analyze your offers' }, - { href: '/offers/dashboard', name: 'Your repository' }, + { href: '/offers/dashboard', name: 'Your dashboard' }, { href: '/offers/features', name: 'Features' }, ]; diff --git a/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx b/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx index 9664e7fb..2cf876f2 100644 --- a/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx +++ b/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx @@ -6,29 +6,20 @@ import OfferPercentileAnalysisText from './OfferPercentileAnalysisText'; import OfferProfileCard from './OfferProfileCard'; import { OVERALL_TAB } from '../constants'; -import type { - Analysis, - AnalysisHighestOffer, - ProfileAnalysis, -} from '~/types/offers'; - -type OfferAnalysisData = { - offer?: AnalysisHighestOffer; - offerAnalysis?: Analysis; -}; +import type { AnalysisUnit, ProfileAnalysis } from '~/types/offers'; type OfferAnalysisContentProps = Readonly<{ - analysis: OfferAnalysisData; + analysis: AnalysisUnit; isSubmission: boolean; tab: string; }>; function OfferAnalysisContent({ - analysis: { offer, offerAnalysis }, + analysis, tab, isSubmission, }: OfferAnalysisContentProps) { - if (!offerAnalysis || !offer || offerAnalysis.noOfOffers === 0) { + if (!analysis || analysis.noOfOffers === 0) { if (tab === OVERALL_TAB) { return (

@@ -47,9 +38,8 @@ function OfferAnalysisContent({ return ( <>

@@ -57,7 +47,7 @@ function OfferAnalysisContent({ ? 'Here are some of the top offers relevant to you:' : 'Relevant top offers:'}

- {offerAnalysis.topPercentileOffers.map((topPercentileOffer) => ( + {analysis.topPercentileOffers.map((topPercentileOffer) => ( (null); + const [analysis, setAnalysis] = useState( + allAnalysis.overallAnalysis, + ); useEffect(() => { if (tab === OVERALL_TAB) { - setAnalysis({ - offer: allAnalysis?.overallHighestOffer, - offerAnalysis: allAnalysis?.overallAnalysis, - }); + setAnalysis(allAnalysis.overallAnalysis); } else { - setAnalysis({ - offer: allAnalysis?.overallHighestOffer, - offerAnalysis: allAnalysis?.companyAnalysis[0], - }); + setAnalysis(allAnalysis.companyAnalysis[parseInt(tab, 10)]); } }, [tab, allAnalysis]); - const tabOptions = [ + const companyTabs = allAnalysis.companyAnalysis.map((value, index) => ({ + label: value.companyName, + value: `${index}`, + })); + + let tabOptions = [ { label: OVERALL_TAB, value: OVERALL_TAB, }, - { - label: allAnalysis?.overallHighestOffer.company.name || '', - value: allAnalysis?.overallHighestOffer.company.id || '', - }, ]; + tabOptions = tabOptions.concat(companyTabs); return ( - <> +
+ {isError && ( +

+ An error occurred while generating profile analysis. +

+ )} {isLoading && } - {analysis && ( + {!isError && !isLoading && (
- {isError && ( -

- An error occurred while generating profile analysis. -

- )} - {!isError && !isLoading && ( -
- - - -
- )} + + +
)} - +
); } diff --git a/apps/portal/src/components/offers/offerAnalysis/OfferPercentileAnalysisText.tsx b/apps/portal/src/components/offers/offerAnalysis/OfferPercentileAnalysisText.tsx index 9b77f209..6ab2f7a6 100644 --- a/apps/portal/src/components/offers/offerAnalysis/OfferPercentileAnalysisText.tsx +++ b/apps/portal/src/components/offers/offerAnalysis/OfferPercentileAnalysisText.tsx @@ -1,18 +1,16 @@ import { OVERALL_TAB } from '../constants'; -import type { Analysis } from '~/types/offers'; +import type { AnalysisUnit } from '~/types/offers'; type OfferPercentileAnalysisTextProps = Readonly<{ - companyName: string; + analysis: AnalysisUnit; isSubmission: boolean; - offerAnalysis: Analysis; tab: string; }>; export default function OfferPercentileAnalysisText({ tab, - companyName, - offerAnalysis: { noOfOffers, percentile }, + analysis: { noOfOffers, percentile, companyName }, isSubmission, }: OfferPercentileAnalysisTextProps) { return tab === OVERALL_TAB ? ( diff --git a/apps/portal/src/components/offers/offerAnalysis/OfferProfileCard.tsx b/apps/portal/src/components/offers/offerAnalysis/OfferProfileCard.tsx index 6be21d1b..59a2019f 100644 --- a/apps/portal/src/components/offers/offerAnalysis/OfferProfileCard.tsx +++ b/apps/portal/src/components/offers/offerAnalysis/OfferProfileCard.tsx @@ -47,11 +47,13 @@ export default function OfferProfileCard({

{profileName}

-
- - Current: - {previousCompanies[0]} -
+ {previousCompanies.length > 0 && ( +
+ + Current: + {previousCompanies[0]} +
+ )}
YOE: diff --git a/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx b/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx index 351e8c4c..efc0db79 100644 --- a/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx +++ b/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx @@ -34,7 +34,7 @@ export default function OffersProfileSave({ }, onSuccess: () => { showToast({ - title: `Saved to your repository!`, + title: `Saved to your dashboard!`, variant: 'success', }); }, @@ -95,8 +95,8 @@ export default function OffersProfileSave({

If you do not want to keep the edit link, you can opt to save this - profile under your account's respository. It will still only be - editable by you. + profile under your account's dashboard. It will still only be editable + by you.

); } diff --git a/apps/portal/src/components/offers/profile/ProfileDetails.tsx b/apps/portal/src/components/offers/profile/ProfileDetails.tsx index 14b585cd..3f61060b 100644 --- a/apps/portal/src/components/offers/profile/ProfileDetails.tsx +++ b/apps/portal/src/components/offers/profile/ProfileDetails.tsx @@ -115,7 +115,15 @@ function ProfileAnalysis({ return (
- + {!analysis ? ( +

No analysis available.

+ ) : ( + + )} {isEditable && (