From 1ea1afc8a2d44588083b283a310db775dbd98367 Mon Sep 17 00:00:00 2001 From: hpkoh <53825802+hpkoh@users.noreply.github.com> Date: Mon, 31 Oct 2022 02:48:56 +0800 Subject: [PATCH] [questions][feat] sort answers, comments (#457) Co-authored-by: Jeff Sieu --- .../migration.sql | 39 +++ .../migration.sql | 2 + apps/portal/prisma/schema.prisma | 61 ++-- .../questions/ContributeQuestionCard.tsx | 98 +++--- .../questions/PaginationLoadMoreButton.tsx | 25 ++ .../questions/QuestionSearchBar.tsx | 70 +--- .../questions/SortOptionsSelect.tsx | 69 ++++ .../card/question/BaseQuestionCard.tsx | 28 +- .../forms/ContributeQuestionForm.tsx | 24 +- .../forms/CreateQuestionEncounterForm.tsx | 19 +- .../questions/typeahead/ExpandedTypeahead.tsx | 21 +- .../questions/typeahead/LocationTypeahead.tsx | 66 +++- .../questions/typeahead/RoleTypeahead.tsx | 11 +- .../answer/[answerId]/[answerSlug]/index.tsx | 108 ++++--- .../[questionId]/[questionSlug]/index.tsx | 255 ++++++++------- apps/portal/src/pages/questions/browse.tsx | 140 ++++---- apps/portal/src/pages/questions/lists.tsx | 4 +- .../src/server/router/locations-router.ts | 2 + .../questions-answer-comment-router.ts | 52 ++- .../questions-answer-comment-user-router.ts | 276 +++++++++++----- .../questions/questions-answer-router.ts | 52 ++- .../questions/questions-answer-user-router.ts | 278 +++++++++++----- .../router/questions/questions-list-router.ts | 8 +- .../questions-question-comment-router.ts | 51 ++- .../questions-question-comment-user-router.ts | 281 +++++++++++----- .../questions-question-encounter-router.ts | 43 +-- ...uestions-question-encounter-user-router.ts | 30 +- .../questions/questions-question-router.ts | 101 +++--- .../questions-question-user-router.ts | 305 +++++++++++++----- apps/portal/src/types/questions.d.ts | 32 +- apps/portal/src/utils/questions/constants.ts | 41 --- .../questions/relabelQuestionAggregates.ts | 8 +- .../questions/server/aggregate-encounters.ts | 61 +++- .../src/utils/questions/useDefaultLocation.ts | 30 +- apps/portal/src/utils/questions/useVote.ts | 114 +++---- 35 files changed, 1854 insertions(+), 951 deletions(-) create mode 100644 apps/portal/prisma/migrations/20221030121147_use_roles_and_location_table/migration.sql create mode 100644 apps/portal/prisma/migrations/20221030133638_add_theory_enum/migration.sql create mode 100644 apps/portal/src/components/questions/PaginationLoadMoreButton.tsx create mode 100644 apps/portal/src/components/questions/SortOptionsSelect.tsx diff --git a/apps/portal/prisma/migrations/20221030121147_use_roles_and_location_table/migration.sql b/apps/portal/prisma/migrations/20221030121147_use_roles_and_location_table/migration.sql new file mode 100644 index 00000000..df5103e4 --- /dev/null +++ b/apps/portal/prisma/migrations/20221030121147_use_roles_and_location_table/migration.sql @@ -0,0 +1,39 @@ +/* + Warnings: + + - You are about to drop the column `location` on the `QuestionsQuestionEncounter` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "QuestionsQuestionEncounter" DROP COLUMN "location", +ADD COLUMN "cityId" TEXT, +ADD COLUMN "countryId" TEXT, +ADD COLUMN "stateId" TEXT, +ALTER COLUMN "companyId" DROP NOT NULL; + +-- CreateIndex +CREATE INDEX "QuestionsAnswer_updatedAt_id_idx" ON "QuestionsAnswer"("updatedAt", "id"); + +-- CreateIndex +CREATE INDEX "QuestionsAnswer_upvotes_id_idx" ON "QuestionsAnswer"("upvotes", "id"); + +-- CreateIndex +CREATE INDEX "QuestionsAnswerComment_updatedAt_id_idx" ON "QuestionsAnswerComment"("updatedAt", "id"); + +-- CreateIndex +CREATE INDEX "QuestionsAnswerComment_upvotes_id_idx" ON "QuestionsAnswerComment"("upvotes", "id"); + +-- CreateIndex +CREATE INDEX "QuestionsQuestionComment_updatedAt_id_idx" ON "QuestionsQuestionComment"("updatedAt", "id"); + +-- CreateIndex +CREATE INDEX "QuestionsQuestionComment_upvotes_id_idx" ON "QuestionsQuestionComment"("upvotes", "id"); + +-- AddForeignKey +ALTER TABLE "QuestionsQuestionEncounter" ADD CONSTRAINT "QuestionsQuestionEncounter_countryId_fkey" FOREIGN KEY ("countryId") REFERENCES "Country"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "QuestionsQuestionEncounter" ADD CONSTRAINT "QuestionsQuestionEncounter_stateId_fkey" FOREIGN KEY ("stateId") REFERENCES "State"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "QuestionsQuestionEncounter" ADD CONSTRAINT "QuestionsQuestionEncounter_cityId_fkey" FOREIGN KEY ("cityId") REFERENCES "City"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/portal/prisma/migrations/20221030133638_add_theory_enum/migration.sql b/apps/portal/prisma/migrations/20221030133638_add_theory_enum/migration.sql new file mode 100644 index 00000000..47b835b1 --- /dev/null +++ b/apps/portal/prisma/migrations/20221030133638_add_theory_enum/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "QuestionsQuestionType" ADD VALUE 'THEORY'; diff --git a/apps/portal/prisma/schema.prisma b/apps/portal/prisma/schema.prisma index 625893c4..d9c273b7 100644 --- a/apps/portal/prisma/schema.prisma +++ b/apps/portal/prisma/schema.prisma @@ -107,27 +107,30 @@ model Company { } model Country { - id String @id - name String @unique - code String @unique - states State[] + id String @id + name String @unique + code String @unique + states State[] + questionsQuestionEncounters QuestionsQuestionEncounter[] } model State { - id String @id - name String - countryId String - cities City[] - country Country @relation(fields: [countryId], references: [id]) + id String @id + name String + countryId String + cities City[] + country Country @relation(fields: [countryId], references: [id]) + questionsQuestionEncounters QuestionsQuestionEncounter[] @@unique([name, countryId]) } model City { - id String @id - name String - stateId String - state State @relation(fields: [stateId], references: [id]) + id String @id + name String + stateId String + state State @relation(fields: [stateId], references: [id]) + questionsQuestionEncounters QuestionsQuestionEncounter[] @@unique([name, stateId]) } @@ -423,6 +426,7 @@ enum QuestionsQuestionType { CODING SYSTEM_DESIGN BEHAVIORAL + THEORY } model QuestionsQuestion { @@ -435,12 +439,12 @@ model QuestionsQuestion { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - encounters QuestionsQuestionEncounter[] - votes QuestionsQuestionVote[] - comments QuestionsQuestionComment[] - answers QuestionsAnswer[] - QuestionsListQuestionEntry QuestionsListQuestionEntry[] + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + encounters QuestionsQuestionEncounter[] + votes QuestionsQuestionVote[] + comments QuestionsQuestionComment[] + answers QuestionsAnswer[] + questionsListQuestionEntries QuestionsListQuestionEntry[] @@index([lastSeenAt, id]) @@index([upvotes, id]) @@ -450,14 +454,18 @@ model QuestionsQuestionEncounter { id String @id @default(cuid()) questionId String userId String? - // TODO: sync with models (location, role) - companyId String - location String @db.Text + companyId String? + countryId String? + stateId String? + cityId String? role String @db.Text seenAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + country Country? @relation(fields: [countryId], references: [id], onDelete: SetNull) + state State? @relation(fields: [stateId], references: [id], onDelete: SetNull) + city City? @relation(fields: [cityId], references: [id], onDelete: SetNull) company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull) user User? @relation(fields: [userId], references: [id], onDelete: SetNull) question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) @@ -489,6 +497,9 @@ model QuestionsQuestionComment { user User? @relation(fields: [userId], references: [id], onDelete: SetNull) question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) votes QuestionsQuestionCommentVote[] + + @@index([updatedAt, id]) + @@index([upvotes, id]) } model QuestionsQuestionCommentVote { @@ -518,6 +529,9 @@ model QuestionsAnswer { question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade) votes QuestionsAnswerVote[] comments QuestionsAnswerComment[] + + @@index([updatedAt, id]) + @@index([upvotes, id]) } model QuestionsAnswerVote { @@ -546,6 +560,9 @@ model QuestionsAnswerComment { user User? @relation(fields: [userId], references: [id], onDelete: SetNull) answer QuestionsAnswer @relation(fields: [answerId], references: [id], onDelete: Cascade) votes QuestionsAnswerCommentVote[] + + @@index([updatedAt, id]) + @@index([upvotes, id]) } model QuestionsAnswerCommentVote { diff --git a/apps/portal/src/components/questions/ContributeQuestionCard.tsx b/apps/portal/src/components/questions/ContributeQuestionCard.tsx index e9bf5c44..f4256e8d 100644 --- a/apps/portal/src/components/questions/ContributeQuestionCard.tsx +++ b/apps/portal/src/components/questions/ContributeQuestionCard.tsx @@ -28,54 +28,56 @@ export default function ContributeQuestionCard({ }; return ( - + + + ); } diff --git a/apps/portal/src/components/questions/PaginationLoadMoreButton.tsx b/apps/portal/src/components/questions/PaginationLoadMoreButton.tsx new file mode 100644 index 00000000..0d6a55be --- /dev/null +++ b/apps/portal/src/components/questions/PaginationLoadMoreButton.tsx @@ -0,0 +1,25 @@ +import type { UseInfiniteQueryResult } from 'react-query'; +import { Button } from '@tih/ui'; + +export type PaginationLoadMoreButtonProps = { + query: UseInfiniteQueryResult; +}; + +export default function PaginationLoadMoreButton( + props: PaginationLoadMoreButtonProps, +) { + const { + query: { hasNextPage, isFetchingNextPage, fetchNextPage }, + } = props; + return ( +