From 633593037ced6cc951864f592fa51fda62c5ab28 Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Fri, 31 May 2024 19:02:32 +0100 Subject: [PATCH 1/8] add expense comments feature --- .../migration.sql | 16 ++++ prisma/schema.prisma | 12 +++ .../[expenseId]/edit/comment-form.tsx | 81 +++++++++++++++++++ .../[expenseId]/edit/comment-item.tsx | 30 +++++++ .../[expenseId]/edit/comments-list.tsx | 59 ++++++++++++++ .../expenses/[expenseId]/edit/page.tsx | 4 + src/lib/api.ts | 50 +++++++++++- src/lib/schemas.ts | 6 ++ 8 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20240531162642_add_expense_comments/migration.sql create mode 100644 src/app/groups/[groupId]/expenses/[expenseId]/edit/comment-form.tsx create mode 100644 src/app/groups/[groupId]/expenses/[expenseId]/edit/comment-item.tsx create mode 100644 src/app/groups/[groupId]/expenses/[expenseId]/edit/comments-list.tsx diff --git a/prisma/migrations/20240531162642_add_expense_comments/migration.sql b/prisma/migrations/20240531162642_add_expense_comments/migration.sql new file mode 100644 index 00000000..0db8cfa1 --- /dev/null +++ b/prisma/migrations/20240531162642_add_expense_comments/migration.sql @@ -0,0 +1,16 @@ +-- CreateTable +CREATE TABLE "ExpenseComment" ( + "id" TEXT NOT NULL, + "comment" TEXT NOT NULL, + "time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "expenseId" TEXT, + "participantId" TEXT NOT NULL, + + CONSTRAINT "ExpenseComment_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "ExpenseComment" ADD CONSTRAINT "ExpenseComment_expenseId_fkey" FOREIGN KEY ("expenseId") REFERENCES "Expense"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ExpenseComment" ADD CONSTRAINT "ExpenseComment_participantId_fkey" FOREIGN KEY ("participantId") REFERENCES "Participant"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2989f3c9..26820b72 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -28,6 +28,7 @@ model Participant { groupId String expensesPaidBy Expense[] expensesPaidFor ExpensePaidFor[] + expenseComments ExpenseComment[] } model Category { @@ -53,9 +54,20 @@ model Expense { splitMode SplitMode @default(EVENLY) createdAt DateTime @default(now()) documents ExpenseDocument[] + comments ExpenseComment[] notes String? } +model ExpenseComment { + id String @id + comment String + time DateTime @default(now()) + Expense Expense? @relation(fields: [expenseId], references: [id]) + expenseId String? + participantId String + participant Participant @relation(fields: [participantId], references: [id], onDelete: Cascade) +} + model ExpenseDocument { id String @id url String diff --git a/src/app/groups/[groupId]/expenses/[expenseId]/edit/comment-form.tsx b/src/app/groups/[groupId]/expenses/[expenseId]/edit/comment-form.tsx new file mode 100644 index 00000000..1ab1bbc7 --- /dev/null +++ b/src/app/groups/[groupId]/expenses/[expenseId]/edit/comment-form.tsx @@ -0,0 +1,81 @@ +'use client' +import { SubmitButton } from '@/components/submit-button' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, +} from '@/components/ui/form' +import { Textarea } from '@/components/ui/textarea' +import { getComment, getGroup } from '@/lib/api' +import { useActiveUser } from '@/lib/hooks' +import { CommentFormValues, commentFormSchema } from '@/lib/schemas' +import { zodResolver } from '@hookform/resolvers/zod' +import { Save } from 'lucide-react' +import { useForm } from 'react-hook-form' + +export type Props = { + group: NonNullable>> + comment?: NonNullable>> + onSubmit: (values: CommentFormValues, participantId: string) => Promise +} + +export function CommentForm({ group, comment, onSubmit }: Props) { + const isCreate = comment === undefined + const activeUserId = useActiveUser(group.id) + + const form = useForm({ + resolver: zodResolver(commentFormSchema), + defaultValues: comment + ? { + comment: comment.comment, + } + : { + comment: '', + }, + }) + + const submit = async (values: CommentFormValues) => { + return onSubmit(values, activeUserId!) + } + + return ( +
+ + + + Add Comment + + + ( + + Comment + +