From 65a8618e547b478773b509f08626a9dfbb0de02a Mon Sep 17 00:00:00 2001 From: Bryann Yeap Kok Keong Date: Mon, 24 Oct 2022 18:40:20 +0800 Subject: [PATCH 1/9] [offers][chore] Add a secondary sorting by monthYearReceived descending in addition to other primary sorting filters applied --- .../portal/src/server/router/offers/offers.ts | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/apps/portal/src/server/router/offers/offers.ts b/apps/portal/src/server/router/offers/offers.ts index 1a1bd354..b333fa66 100644 --- a/apps/portal/src/server/router/offers/offers.ts +++ b/apps/portal/src/server/router/offers/offers.ts @@ -103,22 +103,32 @@ export const offersRouter = createRouter().query('list', { monthYearReceived: order, } : sortingKey === sortingKeysMap.totalCompensation - ? { - offersIntern: { - monthlySalary: { - baseValue: order, + ? [ + { + offersIntern: { + monthlySalary: { + baseValue: order, + }, }, }, - } + { + monthYearReceived: 'desc', + }, + ] : sortingKey === sortingKeysMap.totalYoe - ? { - profile: { - background: { - totalYoe: order, + ? [ + { + profile: { + background: { + totalYoe: order, + }, }, }, - } - : undefined, + { + monthYearReceived: 'desc', + }, + ] + : { monthYearReceived: 'desc' }, where: { AND: [ { @@ -207,22 +217,32 @@ export const offersRouter = createRouter().query('list', { monthYearReceived: order, } : sortingKey === sortingKeysMap.totalCompensation - ? { - offersFullTime: { - totalCompensation: { - baseValue: order, + ? [ + { + offersIntern: { + monthlySalary: { + baseValue: order, + }, }, }, - } + { + monthYearReceived: 'desc', + }, + ] : sortingKey === sortingKeysMap.totalYoe - ? { - profile: { - background: { - totalYoe: order, + ? [ + { + profile: { + background: { + totalYoe: order, + }, }, }, - } - : undefined, + { + monthYearReceived: 'desc', + }, + ] + : { monthYearReceived: 'desc' }, where: { AND: [ { From ef5892a0d684015da3da4d9a428867e0642332ea Mon Sep 17 00:00:00 2001 From: Stuart Long Chay Boon Date: Mon, 24 Oct 2022 20:56:28 +0800 Subject: [PATCH 2/9] [offers][feat] add random name generator --- apps/portal/package.json | 1 + apps/portal/src/utils/offers/randomNameGenerator.ts | 13 +++++++++++++ yarn.lock | 5 +++++ 3 files changed, 19 insertions(+) create mode 100644 apps/portal/src/utils/offers/randomNameGenerator.ts diff --git a/apps/portal/package.json b/apps/portal/package.json index 208b1940..a8a184d8 100644 --- a/apps/portal/package.json +++ b/apps/portal/package.json @@ -38,6 +38,7 @@ "react-popper-tooltip": "^4.4.2", "react-query": "^3.39.2", "superjson": "^1.10.0", + "unique-names-generator": "^4.7.1", "zod": "^3.18.0" }, "devDependencies": { diff --git a/apps/portal/src/utils/offers/randomNameGenerator.ts b/apps/portal/src/utils/offers/randomNameGenerator.ts new file mode 100644 index 00000000..ba286197 --- /dev/null +++ b/apps/portal/src/utils/offers/randomNameGenerator.ts @@ -0,0 +1,13 @@ +import type { Config } from 'unique-names-generator'; +import { adjectives, animals,colors, uniqueNamesGenerator } from 'unique-names-generator'; + +const customConfig: Config = { + dictionaries: [adjectives, colors, animals], + length: 3, + separator: '-', +}; + + +export default function generateRandomName(): string { + return uniqueNamesGenerator(customConfig) +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index f5517ea1..f2dd81c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14405,6 +14405,11 @@ unique-filename@^1.1.1: dependencies: unique-slug "^2.0.0" +unique-names-generator@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/unique-names-generator/-/unique-names-generator-4.7.1.tgz#966407b12ba97f618928f77322cfac8c80df5597" + integrity sha512-lMx9dX+KRmG8sq6gulYYpKWZc9RlGsgBR6aoO8Qsm3qvkSJ+3rAymr+TnV8EDMrIrwuFJ4kruzMWM/OpYzPoow== + unique-slug@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz" From e77bb0363982209806b7480e00e252140c3849cd Mon Sep 17 00:00:00 2001 From: Stuart Long Chay Boon Date: Mon, 24 Oct 2022 21:09:33 +0800 Subject: [PATCH 3/9] [offers][chore] integrate random name generator to create profile --- .../router/offers/offers-profile-router.ts | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) 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 d395c9ec..506b961b 100644 --- a/apps/portal/src/server/router/offers/offers-profile-router.ts +++ b/apps/portal/src/server/router/offers/offers-profile-router.ts @@ -1,4 +1,4 @@ -import crypto, { randomUUID } from 'crypto'; +import crypto from 'crypto'; import { z } from 'zod'; import { JobType } from '@prisma/client'; import * as trpc from '@trpc/server'; @@ -10,6 +10,7 @@ import { } from '~/mappers/offers-mappers'; import { baseCurrencyString } from '~/utils/offers/currency'; import { convert } from '~/utils/offers/currency/currencyExchange'; +import generateRandomName from '~/utils/offers/randomNameGenerator'; import { createValidationRegex } from '~/utils/offers/zodRegex'; import { createRouter } from '../context'; @@ -266,6 +267,24 @@ export const offersProfileRouter = createRouter() .update(Date.now().toString()) .digest('hex'); + // Generate random name until unique + let uniqueName: string = generateRandomName(); + + let sameNameProfiles = await ctx.prisma.offersProfile.findMany({ + where: { + profileName: uniqueName + } + }) + + while (sameNameProfiles.length !== 0) { + uniqueName = generateRandomName(); + sameNameProfiles = await ctx.prisma.offersProfile.findMany({ + where: { + profileName: uniqueName + } + }) + } + const profile = await ctx.prisma.offersProfile.create({ data: { background: { @@ -538,7 +557,7 @@ export const offersProfileRouter = createRouter() }), ), }, - profileName: randomUUID().substring(0, 10), + profileName: uniqueName, }, }); From 3c8029625355c29d090596a3e401e9cc2a8f545e Mon Sep 17 00:00:00 2001 From: Stuart Long Chay Boon Date: Mon, 24 Oct 2022 21:27:40 +0800 Subject: [PATCH 4/9] [offers][refactor] refactor random name generator code --- .../router/offers/offers-profile-router.ts | 17 +------------ .../src/utils/offers/randomNameGenerator.ts | 24 +++++++++++++++++-- 2 files changed, 23 insertions(+), 18 deletions(-) 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 506b961b..c29dfde5 100644 --- a/apps/portal/src/server/router/offers/offers-profile-router.ts +++ b/apps/portal/src/server/router/offers/offers-profile-router.ts @@ -268,22 +268,7 @@ export const offersProfileRouter = createRouter() .digest('hex'); // Generate random name until unique - let uniqueName: string = generateRandomName(); - - let sameNameProfiles = await ctx.prisma.offersProfile.findMany({ - where: { - profileName: uniqueName - } - }) - - while (sameNameProfiles.length !== 0) { - uniqueName = generateRandomName(); - sameNameProfiles = await ctx.prisma.offersProfile.findMany({ - where: { - profileName: uniqueName - } - }) - } + const uniqueName: string = await generateRandomName(); const profile = await ctx.prisma.offersProfile.create({ data: { diff --git a/apps/portal/src/utils/offers/randomNameGenerator.ts b/apps/portal/src/utils/offers/randomNameGenerator.ts index ba286197..ff02e503 100644 --- a/apps/portal/src/utils/offers/randomNameGenerator.ts +++ b/apps/portal/src/utils/offers/randomNameGenerator.ts @@ -1,5 +1,8 @@ import type { Config } from 'unique-names-generator'; import { adjectives, animals,colors, uniqueNamesGenerator } from 'unique-names-generator'; +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient() const customConfig: Config = { dictionaries: [adjectives, colors, animals], @@ -8,6 +11,23 @@ const customConfig: Config = { }; -export default function generateRandomName(): string { - return uniqueNamesGenerator(customConfig) +export default async function generateRandomName(): Promise { + let uniqueName: string = uniqueNamesGenerator(customConfig); + + let sameNameProfiles = await prisma.offersProfile.findMany({ + where: { + profileName: uniqueName + } + }) + + while (sameNameProfiles.length !== 0) { + uniqueName = uniqueNamesGenerator(customConfig); + sameNameProfiles = await prisma.offersProfile.findMany({ + where: { + profileName: uniqueName + } + }) + } + + return uniqueName } \ No newline at end of file From c188405de03da34a93346a8a26bdb8e6ff2fedfa Mon Sep 17 00:00:00 2001 From: Stuart Long Chay Boon Date: Mon, 24 Oct 2022 21:39:49 +0800 Subject: [PATCH 5/9] [offers][chore] create random string generator for token --- .../router/offers/offers-profile-router.ts | 4 ++-- ...andomNameGenerator.ts => randomGenerator.ts} | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) rename apps/portal/src/utils/offers/{randomNameGenerator.ts => randomGenerator.ts} (62%) 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 c29dfde5..9cac7feb 100644 --- a/apps/portal/src/server/router/offers/offers-profile-router.ts +++ b/apps/portal/src/server/router/offers/offers-profile-router.ts @@ -10,7 +10,7 @@ import { } from '~/mappers/offers-mappers'; import { baseCurrencyString } from '~/utils/offers/currency'; import { convert } from '~/utils/offers/currency/currencyExchange'; -import generateRandomName from '~/utils/offers/randomNameGenerator'; +import { generateRandomName, generateRandomStringForToken } from '~/utils/offers/randomGenerator'; import { createValidationRegex } from '~/utils/offers/zodRegex'; import { createRouter } from '../context'; @@ -264,7 +264,7 @@ export const offersProfileRouter = createRouter() // TODO: add more const token = crypto .createHash('sha256') - .update(Date.now().toString()) + .update(Date.now().toString() + generateRandomStringForToken()) .digest('hex'); // Generate random name until unique diff --git a/apps/portal/src/utils/offers/randomNameGenerator.ts b/apps/portal/src/utils/offers/randomGenerator.ts similarity index 62% rename from apps/portal/src/utils/offers/randomNameGenerator.ts rename to apps/portal/src/utils/offers/randomGenerator.ts index ff02e503..c0a05ac9 100644 --- a/apps/portal/src/utils/offers/randomNameGenerator.ts +++ b/apps/portal/src/utils/offers/randomGenerator.ts @@ -1,4 +1,5 @@ -import type { Config } from 'unique-names-generator'; +import type { Config} from 'unique-names-generator'; +import { countries, names } from 'unique-names-generator'; import { adjectives, animals,colors, uniqueNamesGenerator } from 'unique-names-generator'; import { PrismaClient } from '@prisma/client'; @@ -10,8 +11,7 @@ const customConfig: Config = { separator: '-', }; - -export default async function generateRandomName(): Promise { +export async function generateRandomName(): Promise { let uniqueName: string = uniqueNamesGenerator(customConfig); let sameNameProfiles = await prisma.offersProfile.findMany({ @@ -30,4 +30,15 @@ export default async function generateRandomName(): Promise { } return uniqueName +} + +const tokenConfig: Config = { + dictionaries: [adjectives, colors, animals, countries, names] + .sort((_a, _b) => 0.5 - Math.random()), + length: 5, + separator: '-', +}; + +export function generateRandomStringForToken(): string { + return uniqueNamesGenerator(tokenConfig) } \ No newline at end of file From e5c2082bf23c2b04cff99fdd5977a30970937c92 Mon Sep 17 00:00:00 2001 From: Zhang Ziqing <69516975+ziqing26@users.noreply.github.com> Date: Mon, 24 Oct 2022 22:00:48 +0800 Subject: [PATCH 6/9] [offers][feat] add landing page and fix comment bugs (#422) * [offers][fix] fix create commnet and update title * [offers][fix] update tab name * [offers][feat] add landing page --- .../src/components/offers/OffersNavigation.ts | 5 +- .../src/components/offers/OffersTitle.tsx | 4 +- .../offers/landing/LeftTextCard.tsx | 54 ++++ .../offers/landing/RightTextCard.tsx | 54 ++++ .../offers/profile/ProfileComments.tsx | 39 ++- .../offers/profile/comments/CommentCard.tsx | 6 +- apps/portal/src/pages/offers/home.tsx | 48 ++++ apps/portal/src/pages/offers/index.tsx | 272 +++++++++++++++--- .../pages/offers/profile/[offerProfileId].tsx | 4 +- apps/portal/src/utils/offers/time.tsx | 6 +- 10 files changed, 443 insertions(+), 49 deletions(-) create mode 100644 apps/portal/src/components/offers/landing/LeftTextCard.tsx create mode 100644 apps/portal/src/components/offers/landing/RightTextCard.tsx create mode 100644 apps/portal/src/pages/offers/home.tsx diff --git a/apps/portal/src/components/offers/OffersNavigation.ts b/apps/portal/src/components/offers/OffersNavigation.ts index cfa314dc..9b340cec 100644 --- a/apps/portal/src/components/offers/OffersNavigation.ts +++ b/apps/portal/src/components/offers/OffersNavigation.ts @@ -1,13 +1,14 @@ import type { ProductNavigationItems } from '~/components/global/ProductNavigation'; const navigation: ProductNavigationItems = [ - { href: '/offers/submit', name: 'Benchmark your offer' }, + { href: '/offers/home', name: 'Home' }, + { href: '/offers/submit', name: 'Analyse your offers' }, ]; const config = { navigation, showGlobalNav: false, - title: 'Tech Offers Repo', + title: 'Offer Profile Repository', titleHref: '/offers', }; diff --git a/apps/portal/src/components/offers/OffersTitle.tsx b/apps/portal/src/components/offers/OffersTitle.tsx index 2668ac4e..52798611 100644 --- a/apps/portal/src/components/offers/OffersTitle.tsx +++ b/apps/portal/src/components/offers/OffersTitle.tsx @@ -3,14 +3,14 @@ export default function OffersTitle() { <>

- Tech Handbook Offers Repo + Offer Profile Repository

Reveal profile stories behind offers
- Benchmark your offers and profiles, learn from other's offer profile, + Click into offers to view profiles, benchmark your offers and profiles, and discuss with the community
diff --git a/apps/portal/src/components/offers/landing/LeftTextCard.tsx b/apps/portal/src/components/offers/landing/LeftTextCard.tsx new file mode 100644 index 00000000..27886018 --- /dev/null +++ b/apps/portal/src/components/offers/landing/LeftTextCard.tsx @@ -0,0 +1,54 @@ +import type { ReactNode } from 'react'; + +type LeftTextCardProps = Readonly<{ + description: string; + icon: ReactNode; + imageAlt: string; + imageSrc: string; + title: string; +}>; + +const baseUrl = '/offers/home'; +export default function LeftTextCard({ + description, + icon, + imageAlt, + imageSrc, + title, +}: LeftTextCardProps) { + return ( +
+
+
+
+ + {icon} + +
+
+

+ {title} +

+

{description}

+ +
+
+
+
+
+ {imageAlt} +
+
+
+ ); +} diff --git a/apps/portal/src/components/offers/landing/RightTextCard.tsx b/apps/portal/src/components/offers/landing/RightTextCard.tsx new file mode 100644 index 00000000..551c246a --- /dev/null +++ b/apps/portal/src/components/offers/landing/RightTextCard.tsx @@ -0,0 +1,54 @@ +import type { ReactNode } from 'react'; + +type RightTextCarddProps = Readonly<{ + description: string; + icon: ReactNode; + imageAlt: string; + imageSrc: string; + title: string; +}>; + +const baseUrl = '/offers/home'; +export default function RightTextCard({ + description, + icon, + imageAlt, + imageSrc, + title, +}: RightTextCarddProps) { + return ( +
+
+
+
+ + {icon} + +
+
+

+ {title} +

+

{description}

+ +
+
+
+
+
+ {imageAlt} +
+
+
+ ); +} diff --git a/apps/portal/src/components/offers/profile/ProfileComments.tsx b/apps/portal/src/components/offers/profile/ProfileComments.tsx index 5a8ba614..ebed5bfd 100644 --- a/apps/portal/src/components/offers/profile/ProfileComments.tsx +++ b/apps/portal/src/components/offers/profile/ProfileComments.tsx @@ -142,6 +142,39 @@ export default function ProfileComments({ />

Discussions

+ {isEditable || session?.user?.name ? ( +
+