From 9c1cefd4edfbf58895176da7bfe6c08fff859695 Mon Sep 17 00:00:00 2001 From: Denis Lugowski Date: Fri, 18 Apr 2025 18:58:06 +0200 Subject: [PATCH] feat(frontend): Add ogranization invitation --- .../components/InviteMemberModal.vue | 28 +--- legalconsenthub/composables/useBetterAuth.ts | 73 ++++++++++- legalconsenthub/package.json | 3 +- .../pages/accept-invitation/[id].vue | 90 +++++++++++++ legalconsenthub/pnpm-lock.yaml | 124 ++++++++++++++++++ legalconsenthub/server/utils/auth.ts | 16 ++- legalconsenthub/server/utils/mail.ts | 3 + legalconsenthub/utils/auth-types.ts | 14 ++ 8 files changed, 325 insertions(+), 26 deletions(-) create mode 100644 legalconsenthub/pages/accept-invitation/[id].vue create mode 100644 legalconsenthub/server/utils/mail.ts diff --git a/legalconsenthub/components/InviteMemberModal.vue b/legalconsenthub/components/InviteMemberModal.vue index 63cd09d..c516796 100644 --- a/legalconsenthub/components/InviteMemberModal.vue +++ b/legalconsenthub/components/InviteMemberModal.vue @@ -29,11 +29,11 @@ diff --git a/legalconsenthub/composables/useBetterAuth.ts b/legalconsenthub/composables/useBetterAuth.ts index 9a173df..c5f761a 100644 --- a/legalconsenthub/composables/useBetterAuth.ts +++ b/legalconsenthub/composables/useBetterAuth.ts @@ -40,10 +40,81 @@ export function useBetterAuth() { ) } + async function getInvitation(invitationId: string): Promise { + return authClient.organization.getInvitation({ + query: { id: invitationId }, + fetchOptions: { + throw: true, + onSuccess: (ctx) => { + return ctx.data + }, + onError: (error) => { + toast.add({ title: 'Fehler beim Einladen', description: error.error.message, color: 'error' }) + } + } + }) + } + + async function inviteMember(email: string, role: 'member' | 'admin') { + await authClient.organization.inviteMember({ + email, + role, + fetchOptions: { + throw: true, + onSuccess: (ctx) => { + if (activeOrganization.value) { + activeOrganization.value = { + ...activeOrganization.value, + invitations: [...(activeOrganization.value?.invitations || []), ctx.data] + } + } + }, + onError: (error) => { + toast.add({ title: 'Fehler beim Einladen', description: error.error.message, color: 'error' }) + } + } + }) + } + + async function acceptInvitation(invitationId: string) { + await authClient.organization.acceptInvitation({ + invitationId, + fetchOptions: { + throw: true, + onSuccess: async () => { + toast.add({ title: 'Invitation accepted', color: 'success' }) + await navigateTo('/') + }, + onError: (ctx) => { + toast.add({ title: 'Error when accepting invitation', description: ctx.error.message, color: 'error' }) + } + } + }) + } + + async function rejectInvitation(invitationId: string) { + await authClient.organization.rejectInvitation({ + invitationId, + fetchOptions: { + throw: true, + onSuccess: () => { + toast.add({ title: 'Invitation rejected', color: 'success' }) + }, + onError: (ctx) => { + toast.add({ title: 'Error when rejecting invitation', description: ctx.error.message, color: 'error' }) + } + } + }) + } + return { activeOrganization, selectedOrgId, createOrganization, - deleteOrganization + deleteOrganization, + getInvitation, + inviteMember, + acceptInvitation, + rejectInvitation } } diff --git a/legalconsenthub/package.json b/legalconsenthub/package.json index 1998c99..cd04c40 100644 --- a/legalconsenthub/package.json +++ b/legalconsenthub/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "build": "nuxt build", - "dev": "nuxt dev", + "dev": "nuxt dev --port 3001", "generate": "nuxt generate", "preview": "nuxt preview", "postinstall": "nuxt prepare && pnpm run fix:bettersqlite", @@ -22,6 +22,7 @@ "better-sqlite3": "11.8.1", "nuxt": "3.16.1", "pinia": "3.0.1", + "resend": "^4.3.0", "vue": "latest", "vue-router": "latest" }, diff --git a/legalconsenthub/pages/accept-invitation/[id].vue b/legalconsenthub/pages/accept-invitation/[id].vue new file mode 100644 index 0000000..bcbce5d --- /dev/null +++ b/legalconsenthub/pages/accept-invitation/[id].vue @@ -0,0 +1,90 @@ +