From cdbf527ea6f4fdf891f59369ce65fabcccf05509 Mon Sep 17 00:00:00 2001 From: Denis Lugowski Date: Tue, 13 May 2025 08:46:02 +0200 Subject: [PATCH] feat(frontend,backend): Create and load comments --- .../legalconsenthub/comment/Comment.kt | 3 + .../comment/CommentRepository.kt | 4 +- .../legalconsenthub/comment/CommentService.kt | 11 +- legalconsenthub/components/FormEngine.vue | 92 +- .../applicationForm/useApplicationForm.ts | 8 +- .../applicationForm/useApplicationFormApi.ts | 9 +- .../composables/comment/useComment.ts | 73 + .../composables/comment/useCommentApi.ts | 43 + legalconsenthub/composables/useAuth.ts | 7 + legalconsenthub/package.json | 2 +- .../pages/application-forms/[id].vue | 22 +- legalconsenthub/pages/create.vue | 12 +- legalconsenthub/pnpm-lock.yaml | 1214 +++++++++++++---- legalconsenthub/stores/useCommentStore.ts | 98 ++ 14 files changed, 1294 insertions(+), 304 deletions(-) create mode 100644 legalconsenthub/composables/comment/useComment.ts create mode 100644 legalconsenthub/composables/comment/useCommentApi.ts create mode 100644 legalconsenthub/stores/useCommentStore.ts diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt index ba036fc..f15e50b 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt @@ -8,17 +8,20 @@ import jakarta.persistence.AttributeOverrides import jakarta.persistence.Column import jakarta.persistence.Embedded import jakarta.persistence.Entity +import jakarta.persistence.EntityListeners import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn import jakarta.persistence.ManyToOne import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener import java.time.LocalDateTime import java.util.UUID; @Entity +@EntityListeners(AuditingEntityListener::class) class Comment( @Id @GeneratedValue diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt index 84b6d28..5796bb1 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt @@ -1,6 +1,6 @@ package com.betriebsratkanzlei.legalconsenthub.comment -import com.betriebsratkanzlei.legalconsenthub.form_element.FormElement +import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationForm import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository @@ -9,5 +9,5 @@ import java.util.UUID @Repository interface CommentRepository : JpaRepository { - fun findAllByFormElement(formElement: FormElement, pageable: Pageable): Page + fun findAllByApplicationForm(applicationForm: ApplicationForm, pageable: Pageable): Page } diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentService.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentService.kt index cce172c..5ab8a99 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentService.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentService.kt @@ -1,5 +1,6 @@ package com.betriebsratkanzlei.legalconsenthub.comment +import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationFormRepository import com.betriebsratkanzlei.legalconsenthub.error.CommentNotCreatedException import com.betriebsratkanzlei.legalconsenthub.error.CommentNotDeletedException import com.betriebsratkanzlei.legalconsenthub.error.CommentNotFoundException @@ -16,7 +17,7 @@ import java.util.UUID @Service class CommentService( private val commentRepository: CommentRepository, - private val formElementRepository: FormElementRepository, + private val applicationFormRepository: ApplicationFormRepository, private val commentMapper: CommentMapper ) { @@ -36,11 +37,11 @@ class CommentService( return commentRepository.findById(id).orElseThrow { CommentNotFoundException(id) } } - fun getComments(formElementId: UUID): Page { - val formElement = - formElementRepository.findById(formElementId).orElseThrow { FormElementNotFoundException(formElementId) } + fun getComments(applicationFormId: UUID): Page { + val applicationForm = + applicationFormRepository.findById(applicationFormId).orElse(null) val pageable = PageRequest.of(0, 10) - return commentRepository.findAllByFormElement(formElement, pageable) + return commentRepository.findAllByApplicationForm(applicationForm, pageable) } fun updateComment(commentDto: CommentDto): Comment { diff --git a/legalconsenthub/components/FormEngine.vue b/legalconsenthub/components/FormEngine.vue index a722809..e10ea48 100644 --- a/legalconsenthub/components/FormEngine.vue +++ b/legalconsenthub/components/FormEngine.vue @@ -1,30 +1,79 @@ diff --git a/legalconsenthub/composables/applicationForm/useApplicationForm.ts b/legalconsenthub/composables/applicationForm/useApplicationForm.ts index 5c24ff4..dc810f0 100644 --- a/legalconsenthub/composables/applicationForm/useApplicationForm.ts +++ b/legalconsenthub/composables/applicationForm/useApplicationForm.ts @@ -6,8 +6,6 @@ import { } from '~/.api-client' import { useApplicationFormApi } from './useApplicationFormApi' -const currentApplicationForm: Ref = ref() - export function useApplicationForm() { const applicationFormApi = useApplicationFormApi() @@ -15,8 +13,7 @@ export function useApplicationForm() { createApplicationFormDto: CreateApplicationFormDto ): Promise { try { - currentApplicationForm.value = await applicationFormApi.createApplicationForm(createApplicationFormDto) - return currentApplicationForm.value + return await applicationFormApi.createApplicationForm(createApplicationFormDto) } catch (e: unknown) { if (e instanceof ResponseError) { console.error('Failed creating application form:', e.response) @@ -62,8 +59,7 @@ export function useApplicationForm() { } try { - currentApplicationForm.value = await applicationFormApi.updateApplicationForm(id, applicationFormDto) - return currentApplicationForm.value + return await applicationFormApi.updateApplicationForm(id, applicationFormDto) } catch (e: unknown) { if (e instanceof ResponseError) { console.error(`Failed updating application form with ID ${id}:`, e.response) diff --git a/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts b/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts index b1fbbed..e56e7a5 100644 --- a/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts +++ b/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts @@ -1,5 +1,10 @@ -import { ApplicationFormApi, Configuration } from '../../.api-client' -import type { CreateApplicationFormDto, ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client' +import { + ApplicationFormApi, + Configuration, + type CreateApplicationFormDto, + type ApplicationFormDto, + type PagedApplicationFormDto +} from '~/.api-client' import { cleanDoubleSlashes, withoutTrailingSlash } from 'ufo' export function useApplicationFormApi() { diff --git a/legalconsenthub/composables/comment/useComment.ts b/legalconsenthub/composables/comment/useComment.ts new file mode 100644 index 0000000..e063078 --- /dev/null +++ b/legalconsenthub/composables/comment/useComment.ts @@ -0,0 +1,73 @@ +import { type CreateCommentDto, type CommentDto, type PagedCommentDto, ResponseError } from '~/.api-client' +import { useCommentApi } from './useCommentApi' + +export function useComment() { + const commentApi = useCommentApi() + + async function createComment( + applicationFormId: string, + formElementId: string, + createCommentDto: CreateCommentDto + ): Promise { + try { + return await commentApi.createComment(applicationFormId, formElementId, createCommentDto) + } catch (e: unknown) { + if (e instanceof ResponseError) { + console.error('Failed creating comment:', e.response) + } else { + console.error('Failed creating comment:', e) + } + return Promise.reject(e) + } + } + + async function getCommentsByApplicationFormId(applicationFormId: string): Promise { + try { + return await commentApi.getCommentsByApplicationFormId(applicationFormId) + } catch (e: unknown) { + if (e instanceof ResponseError) { + console.error('Failed retrieving comments:', e.response) + } else { + console.error('Failed retrieving comments:', e) + } + return Promise.reject(e) + } + } + + async function updateComment(id?: string, commentDto?: CommentDto): Promise { + if (!id || !commentDto) { + return Promise.reject(new Error('ID or comment DTO missing')) + } + + try { + return await commentApi.updateComment(id, commentDto) + } catch (e: unknown) { + if (e instanceof ResponseError) { + console.error(`Failed updating comment with ID ${id}:`, e.response) + } else { + console.error(`Failed updating comment with ID ${id}:`, e) + } + return Promise.reject(e) + } + } + + async function deleteCommentById(id: string): Promise { + try { + return await commentApi.deleteCommentById(id) + } catch (e: unknown) { + if (e instanceof ResponseError) { + console.error(`Failed deleting comment with ID ${id}:`, e.response) + } else { + console.error(`Failed deleting comment with ID ${id}:`, e) + } + return Promise.reject(e) + } + } + + return { + createComment, + getCommentsByApplicationFormId, + updateComment, + deleteCommentById + } +} diff --git a/legalconsenthub/composables/comment/useCommentApi.ts b/legalconsenthub/composables/comment/useCommentApi.ts new file mode 100644 index 0000000..b2baaab --- /dev/null +++ b/legalconsenthub/composables/comment/useCommentApi.ts @@ -0,0 +1,43 @@ +import { CommentApi, Configuration, type CommentDto, type CreateCommentDto, type PagedCommentDto } from '~/.api-client' +import { cleanDoubleSlashes, withoutTrailingSlash } from 'ufo' + +export function useCommentApi() { + const appBaseUrl = useRuntimeConfig().app.baseURL + const { serverApiBaseUrl, serverApiBasePath, clientProxyBasePath } = useRuntimeConfig().public + const { jwt } = useAuth() + + const basePath = withoutTrailingSlash( + cleanDoubleSlashes(import.meta.client ? appBaseUrl + clientProxyBasePath : serverApiBaseUrl + serverApiBasePath) + ) + + const commentApiClient = new CommentApi( + new Configuration({ basePath, headers: { Authorization: jwt.value ? `Bearer ${jwt.value}` : '' } }) + ) + + async function createComment( + applicationFormId: string, + formElementId: string, + createCommentDto: CreateCommentDto + ): Promise { + return commentApiClient.createComment({ applicationFormId, formElementId, createCommentDto }) + } + + async function getCommentsByApplicationFormId(applicationFormId: string): Promise { + return commentApiClient.getCommentsByApplicationFormId({ applicationFormId }) + } + + async function updateComment(id: string, commentDto: CommentDto): Promise { + return commentApiClient.updateComment({ id, commentDto }) + } + + async function deleteCommentById(id: string): Promise { + return commentApiClient.deleteComment({ id }) + } + + return { + createComment, + getCommentsByApplicationFormId, + updateComment, + deleteCommentById + } +} diff --git a/legalconsenthub/composables/useAuth.ts b/legalconsenthub/composables/useAuth.ts index 9c97e9f..5fa3de9 100644 --- a/legalconsenthub/composables/useAuth.ts +++ b/legalconsenthub/composables/useAuth.ts @@ -5,6 +5,7 @@ import { createAuthClient } from 'better-auth/client' import type { InferSessionFromClient, InferUserFromClient, ClientOptions } from 'better-auth/client' import { organizationClient, jwtClient } from 'better-auth/client/plugins' import type { RouteLocationRaw } from 'vue-router' +import type { UserDto } from '~/.api-client' interface RuntimeAuthConfig { redirectUserTo: RouteLocationRaw | string @@ -103,9 +104,15 @@ export function useAuth() { return res } + const userDto = computed(() => ({ + id: user.value?.id ?? '', + name: user.value?.name ?? 'Unknown' + })) + return { session, user, + userDto, loggedIn: computed(() => !!session.value), signIn: client.signIn, signUp: client.signUp, diff --git a/legalconsenthub/package.json b/legalconsenthub/package.json index aa46e3b..b8dd421 100644 --- a/legalconsenthub/package.json +++ b/legalconsenthub/package.json @@ -17,7 +17,7 @@ "migrate:betterauth": "pnpm dlx @better-auth/cli migrate --config server/utils/auth.ts" }, "dependencies": { - "@nuxt/ui-pro": "3.0.1", + "@nuxt/ui-pro": "3.1.1", "@pinia/nuxt": "0.10.1", "better-auth": "1.1.16", "better-sqlite3": "11.8.1", diff --git a/legalconsenthub/pages/application-forms/[id].vue b/legalconsenthub/pages/application-forms/[id].vue index 97f7c05..5f78817 100644 --- a/legalconsenthub/pages/application-forms/[id].vue +++ b/legalconsenthub/pages/application-forms/[id].vue @@ -19,13 +19,17 @@ @@ -71,4 +75,8 @@ async function onSubmit() { await navigateTo('/') } } + +function openComments(formElementId: string) { + console.log('open comments for', formElementId) +} diff --git a/legalconsenthub/pages/create.vue b/legalconsenthub/pages/create.vue index afbdb79..a963917 100644 --- a/legalconsenthub/pages/create.vue +++ b/legalconsenthub/pages/create.vue @@ -36,14 +36,14 @@