From c7ffd00bb14e6d3f012f6da55daa601866dbb18b Mon Sep 17 00:00:00 2001 From: nezouse Date: Tue, 19 Mar 2024 13:17:51 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=AB=9A=20Add=20comment=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commentValue/commentValueAction.ts | 47 + .../commentValue/commentValueForm.tsx | 64 ++ .../[applicationId]/comments/comments.tsx | 20 +- .../applications/[applicationId]/page.tsx | 2 +- .../migrations/0004_talented_lady_ursula.sql | 18 + .../migrations/meta/0004_snapshot.json | 879 ++++++++++++++++++ src/drizzle/migrations/meta/_journal.json | 7 + src/drizzle/queries/commentValues.ts | 45 + src/drizzle/schema.ts | 20 + 9 files changed, 1095 insertions(+), 7 deletions(-) create mode 100644 src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueAction.ts create mode 100644 src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueForm.tsx create mode 100644 src/drizzle/migrations/0004_talented_lady_ursula.sql create mode 100644 src/drizzle/migrations/meta/0004_snapshot.json create mode 100644 src/drizzle/queries/commentValues.ts diff --git a/src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueAction.ts b/src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueAction.ts new file mode 100644 index 00000000..10897044 --- /dev/null +++ b/src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueAction.ts @@ -0,0 +1,47 @@ +"use server"; + +import { revalidatePath } from "next/cache"; +import { + deleteCommentValue, + insertCommentValue, +} from "@/drizzle/queries/commentValues"; +import { commentValues } from "@/drizzle/schema"; +import { type Session } from "next-auth"; + +import { ApplicationParamsSchema } from "@/lib/paramsValidation"; + +interface CommentValueActionPayload extends ApplicationParamsSchema { + commentId: string; + session: Session | null; + isChecked: boolean; + value: (typeof commentValues.$inferInsert)["value"]; +} + +export async function commentValueAction({ + applicationId, + session, + commentId, + waveId, + isChecked, + value, +}: CommentValueActionPayload) { + if (!session?.user?.id) { + throw new Error("Unauthorized"); + } + + if (isChecked) { + await deleteCommentValue({ + commentId, + userId: session.user.id, + value, + }); + } else { + await insertCommentValue({ + commentId, + userId: session.user.id, + value, + }); + } + + revalidatePath(`/waves/${waveId}/applications/${applicationId}`); +} diff --git a/src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueForm.tsx b/src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueForm.tsx new file mode 100644 index 00000000..ba343b3b --- /dev/null +++ b/src/app/waves/[waveId]/applications/[applicationId]/comments/commentValue/commentValueForm.tsx @@ -0,0 +1,64 @@ +import { getCommentValue } from "@/drizzle/queries/commentValues"; + +import { auth } from "@/lib/auth"; +import { ApplicationParamsSchema } from "@/lib/paramsValidation"; +import { Button } from "@/components/ui/button"; + +import { commentValueAction } from "./commentValueAction"; + +interface CommentValueFormProps extends ApplicationParamsSchema { + commentId: string; +} + +export async function CommentValueForm({ + applicationId, + waveId, + commentId, +}: CommentValueFormProps) { + const session = await auth(); + const applicationValue = await getCommentValue({ + commentId, + userId: session?.user?.id, + }); + + const isUpvoted = applicationValue === "positive"; + const isSpam = applicationValue === "spam"; + + return ( +
+ + +
+ ); +} diff --git a/src/app/waves/[waveId]/applications/[applicationId]/comments/comments.tsx b/src/app/waves/[waveId]/applications/[applicationId]/comments/comments.tsx index 5540e5fe..47475589 100644 --- a/src/app/waves/[waveId]/applications/[applicationId]/comments/comments.tsx +++ b/src/app/waves/[waveId]/applications/[applicationId]/comments/comments.tsx @@ -9,6 +9,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { UserAvatar } from "@/components/ui/userAvatar"; import { AddCommentForm } from "./addCommentForm/addCommentForm"; +import { CommentValueForm } from "./commentValue/commentValueForm"; import { parseMarkdown } from "./parseMarkdown"; const SECTIONS = { @@ -18,9 +19,10 @@ const SECTIONS = { interface CommentsProps { comments: ApplicationWithComments["comments"]; + waveId: number; } -export async function Comments({ comments }: CommentsProps) { +export async function Comments({ comments, waveId }: CommentsProps) { const reviews = comments.filter((comment) => comment.reviews?.isReview); return ( @@ -37,10 +39,10 @@ export async function Comments({ comments }: CommentsProps) { /> - + - + @@ -65,10 +67,10 @@ function SectionButton({ section, elementsAmount }: SectionButtonProps) { ); } -function CommentsList({ comments }: CommentsProps) { +function CommentsList({ comments, waveId }: CommentsProps) { return comments.map((comment) => ( - + )); @@ -76,9 +78,10 @@ function CommentsList({ comments }: CommentsProps) { interface CommentProps { comment: ApplicationWithComments["comments"][number]; + waveId: number; } -export async function Comment({ comment }: CommentProps) { +export async function Comment({ comment, waveId }: CommentProps) { const commentHtml = await parseMarkdown(comment.content); const isReview = comment.reviews?.isReview; @@ -106,6 +109,11 @@ export async function Comment({ comment }: CommentProps) { {formatTime(comment.createdAt)} + diff --git a/src/app/waves/[waveId]/applications/[applicationId]/page.tsx b/src/app/waves/[waveId]/applications/[applicationId]/page.tsx index 03fb7865..5e6cc8ab 100644 --- a/src/app/waves/[waveId]/applications/[applicationId]/page.tsx +++ b/src/app/waves/[waveId]/applications/[applicationId]/page.tsx @@ -43,7 +43,7 @@ export default async function Application({ params }: { params: unknown }) { - + ); } diff --git a/src/drizzle/migrations/0004_talented_lady_ursula.sql b/src/drizzle/migrations/0004_talented_lady_ursula.sql new file mode 100644 index 00000000..3456e3f9 --- /dev/null +++ b/src/drizzle/migrations/0004_talented_lady_ursula.sql @@ -0,0 +1,18 @@ +CREATE TABLE IF NOT EXISTS "commentValue" ( + "commentId" uuid NOT NULL, + "userId" text NOT NULL, + "value" "contentValue" NOT NULL, + CONSTRAINT "commentValue_commentId_userId_pk" PRIMARY KEY("commentId","userId") +); + +DO $$ BEGIN + ALTER TABLE "commentValue" ADD CONSTRAINT "commentValue_commentId_comment_id_fk" FOREIGN KEY ("commentId") REFERENCES "comment"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +DO $$ BEGIN + ALTER TABLE "commentValue" ADD CONSTRAINT "commentValue_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/src/drizzle/migrations/meta/0004_snapshot.json b/src/drizzle/migrations/meta/0004_snapshot.json new file mode 100644 index 00000000..cf58f205 --- /dev/null +++ b/src/drizzle/migrations/meta/0004_snapshot.json @@ -0,0 +1,879 @@ +{ + "id": "b9f92d6e-8769-46ca-aeac-6874709bb781", + "prevId": "3b8839f7-7dde-4ca1-aeca-339dfa534596", + "version": "5", + "dialect": "pg", + "tables": { + "account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {} + }, + "applicationValue": { + "name": "applicationValue", + "schema": "", + "columns": { + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "contentValue", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "applicationValue_applicationId_application_id_fk": { + "name": "applicationValue_applicationId_application_id_fk", + "tableFrom": "applicationValue", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "applicationValue_userId_user_id_fk": { + "name": "applicationValue_userId_user_id_fk", + "tableFrom": "applicationValue", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "applicationValue_applicationId_userId_pk": { + "name": "applicationValue_applicationId_userId_pk", + "columns": [ + "applicationId", + "userId" + ] + } + }, + "uniqueConstraints": {} + }, + "application": { + "name": "application", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entityName": { + "name": "entityName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "duration": { + "name": "duration", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "budget": { + "name": "budget", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "teamSummary": { + "name": "teamSummary", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "idea": { + "name": "idea", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "goals": { + "name": "goals", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requirements": { + "name": "requirements", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tbd": { + "name": "tbd", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "imageId": { + "name": "imageId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "waveId": { + "name": "waveId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "application_imageId_image_id_fk": { + "name": "application_imageId_image_id_fk", + "tableFrom": "application", + "tableTo": "image", + "columnsFrom": [ + "imageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "application_waveId_wave_id_fk": { + "name": "application_waveId_wave_id_fk", + "tableFrom": "application", + "tableTo": "wave", + "columnsFrom": [ + "waveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "application_userId_user_id_fk": { + "name": "application_userId_user_id_fk", + "tableFrom": "application", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "commentValue": { + "name": "commentValue", + "schema": "", + "columns": { + "commentId": { + "name": "commentId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "contentValue", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "commentValue_commentId_comment_id_fk": { + "name": "commentValue_commentId_comment_id_fk", + "tableFrom": "commentValue", + "tableTo": "comment", + "columnsFrom": [ + "commentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "commentValue_userId_user_id_fk": { + "name": "commentValue_userId_user_id_fk", + "tableFrom": "commentValue", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "commentValue_commentId_userId_pk": { + "name": "commentValue_commentId_userId_pk", + "columns": [ + "commentId", + "userId" + ] + } + }, + "uniqueConstraints": {} + }, + "comment": { + "name": "comment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "comment_applicationId_application_id_fk": { + "name": "comment_applicationId_application_id_fk", + "tableFrom": "comment", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "comment_userId_user_id_fk": { + "name": "comment_userId_user_id_fk", + "tableFrom": "comment", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "image": { + "name": "image", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "bytea", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "image_userId_user_id_fk": { + "name": "image_userId_user_id_fk", + "tableFrom": "image", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "imageId": { + "name": "imageId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "member_applicationId_application_id_fk": { + "name": "member_applicationId_application_id_fk", + "tableFrom": "member", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_imageId_image_id_fk": { + "name": "member_imageId_image_id_fk", + "tableFrom": "member", + "tableTo": "image", + "columnsFrom": [ + "imageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "review": { + "name": "review", + "schema": "", + "columns": { + "commentId": { + "name": "commentId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "review_commentId_comment_id_fk": { + "name": "review_commentId_comment_id_fk", + "tableFrom": "review", + "tableTo": "comment", + "columnsFrom": [ + "commentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "review_userId_user_id_fk": { + "name": "review_userId_user_id_fk", + "tableFrom": "review", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "review_applicationId_application_id_fk": { + "name": "review_applicationId_application_id_fk", + "tableFrom": "review", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "review_userId_applicationId_pk": { + "name": "review_userId_applicationId_pk", + "columns": [ + "userId", + "applicationId" + ] + } + }, + "uniqueConstraints": {} + }, + "session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token_pk": { + "name": "verificationToken_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + }, + "wave": { + "name": "wave", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "startsAt": { + "name": "startsAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "endsAt": { + "name": "endsAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "contentValue": { + "name": "contentValue", + "values": { + "positive": "positive", + "spam": "spam" + } + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/drizzle/migrations/meta/_journal.json b/src/drizzle/migrations/meta/_journal.json index d306131e..8c9e034d 100644 --- a/src/drizzle/migrations/meta/_journal.json +++ b/src/drizzle/migrations/meta/_journal.json @@ -29,6 +29,13 @@ "when": 1710778730458, "tag": "0003_solid_black_knight", "breakpoints": false + }, + { + "idx": 4, + "version": "5", + "when": 1710850629549, + "tag": "0004_talented_lady_ursula", + "breakpoints": false } ] } \ No newline at end of file diff --git a/src/drizzle/queries/commentValues.ts b/src/drizzle/queries/commentValues.ts new file mode 100644 index 00000000..8a210800 --- /dev/null +++ b/src/drizzle/queries/commentValues.ts @@ -0,0 +1,45 @@ +import { cache } from "react"; +import { db } from "@/drizzle/db"; +import { commentValues } from "@/drizzle/schema"; +import { and, eq } from "drizzle-orm"; + +type CommentValueQuery = { + commentId: (typeof commentValues.$inferSelect)["commentId"]; + userId: (typeof commentValues.$inferSelect)["userId"] | undefined; +}; + +export const getCommentValue = cache(async (query: CommentValueQuery) => { + if (!query.userId) { + return undefined; + } + + const result = await db.query.commentValues.findFirst({ + where: and( + eq(commentValues.commentId, query.commentId), + eq(commentValues.userId, query.userId), + ), + }); + + return result?.value; +}); + +export function insertCommentValue(data: typeof commentValues.$inferInsert) { + return db + .insert(commentValues) + .values(data) + .onConflictDoUpdate({ + target: [commentValues.userId, commentValues.commentId], + set: { value: data.value }, + }); +} + +export function deleteCommentValue(query: typeof commentValues.$inferSelect) { + return db + .delete(commentValues) + .where( + and( + eq(commentValues.commentId, query.commentId), + eq(commentValues.userId, query.userId), + ), + ); +} diff --git a/src/drizzle/schema.ts b/src/drizzle/schema.ts index a5925bff..bb8c7516 100644 --- a/src/drizzle/schema.ts +++ b/src/drizzle/schema.ts @@ -171,8 +171,28 @@ export const commentsRelations = relations(comments, ({ one }) => ({ references: [users.id], }), reviews: one(reviews), + commentValues: one(commentValues, { + fields: [comments.id], + references: [commentValues.commentId], + }), })); +export const commentValues = pgTable( + "commentValue", + { + commentId: uuid("commentId") + .notNull() + .references(() => comments.id, { onDelete: "cascade" }), + userId: text("userId") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + value: contentValueEnum("value").notNull(), + }, + (table) => ({ + pk: primaryKey({ columns: [table.commentId, table.userId] }), + }), +); + export const reviews = pgTable( "review", {