feat(frontend): Refactor organization, fixed several organization bugs

This commit is contained in:
2025-08-17 09:28:26 +02:00
parent b7b6d02cf2
commit 6090d543c1
14 changed files with 279 additions and 221 deletions

View File

@@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
import { type CreateCommentDto, type CommentDto, ResponseError } from '~/.api-client'
import { useCommentApi } from '~/composables/comment/useCommentApi'
export const useCommentStore = defineStore('comment', () => {
export const useCommentStore = defineStore('Comment', () => {
type FormElementId = string
const commentApi = useCommentApi()
const comments = ref<Record<FormElementId, CommentDto[]>>({})

View File

@@ -0,0 +1,160 @@
import type { ActiveOrganization, Organization, Invitation } from '~/composables/useAuth'
import { useOrganizationApi } from '~/composables/organization/useOrganizationApi'
import type { LegalRole } from '~/server/utils/permissions'
export const useOrganizationStore = defineStore('Organization', () => {
const activeOrganization = ref<ActiveOrganization | null>(null)
const organizations = ref<Organization[]>([])
const invitations = ref<Invitation[]>([])
const organizationApi = useOrganizationApi()
const toast = useToast()
async function createOrganization(name: string, slug: string, logo?: string) {
try {
const { data: slugCheck } = await organizationApi.checkSlugAvailability(slug)
if (!slugCheck?.status) {
toast.add({
title: 'Slug already taken',
description: 'Please choose a different slug',
color: 'error'
})
return Promise.reject()
}
const { data: createdOrganization } = await organizationApi.createOrganization(name, slug, logo)
if (createdOrganization) {
organizations.value.push(createdOrganization)
toast.add({ title: 'Organization created successfully', color: 'success' })
if (createdOrganization.id) {
await setActiveOrganization(createdOrganization.id)
}
return createdOrganization
}
} catch (e) {
toast.add({ title: 'Error creating organization', color: 'error' })
console.error('Error creating organization:', e)
}
}
async function deleteOrganization(organizationId?: string) {
try {
const idToDelete = organizationId ?? activeOrganization.value?.id
if (!idToDelete) {
throw Error(`No organization is selected for deletion`)
}
await organizationApi.deleteOrganization(idToDelete)
organizations.value = organizations.value.filter((org) => org.id !== organizationId)
toast.add({ title: 'Organization deleted successfully', color: 'success' })
} catch (e) {
toast.add({ title: 'Error deleting organization', color: 'error' })
console.error('Error deleting organization:', e)
}
}
async function getInvitation(invitationId: string): Promise<CustomInvitation> {
try {
const { data: invitation } = await organizationApi.getInvitation(invitationId)
return invitation
} catch (e) {
console.error('Error getInvitation:', e)
return null
}
}
async function loadInvitations(organizationId?: string) {
try {
const { data: loadedInvitations } = await organizationApi.listInvitations(organizationId)
if (loadedInvitations) {
invitations.value = loadedInvitations
}
} catch (e) {
toast.add({ title: 'Error loading invitations', color: 'error' })
console.error('Error loading invitations:', e)
}
}
async function inviteMember(email: string, role: LegalRole) {
try {
await organizationApi.inviteMember(email, role)
await loadInvitations()
toast.add({ title: 'Member invited successfully', color: 'success' })
} catch (e) {
toast.add({ title: 'Error inviting member', color: 'error' })
console.error('Error inviting member:', e)
}
}
async function acceptInvitation(invitationId: string) {
try {
await organizationApi.acceptInvitation(invitationId)
await navigateTo('/')
} catch (e) {
toast.add({ title: 'Error accepting invitation', color: 'error' })
console.error('Error accepting invitation:', e)
}
}
async function cancelSentInvitation(invitationId: string) {
try {
await organizationApi.cancelSentInvitation(invitationId)
invitations.value = invitations.value.filter((invitation) => invitation.id !== invitationId)
} catch (e) {
toast.add({ title: 'Error rejecting invitation', color: 'error' })
console.error('Error rejecting invitation:', e)
}
}
async function rejectInvitation(invitationId: string) {
try {
await organizationApi.rejectInvitation(invitationId)
invitations.value = invitations.value.filter((invitation) => invitation.id !== invitationId)
} catch (e) {
toast.add({ title: 'Error rejecting invitation', color: 'error' })
console.error('Error rejecting invitation:', e)
}
}
async function loadOrganizations() {
try {
const { data: loadedOrganizations } = await organizationApi.loadOrganizations()
if (loadedOrganizations) {
organizations.value = loadedOrganizations
}
} catch (e) {
toast.add({ title: 'Error loading organizations', color: 'error' })
console.error('Error loading organizations:', e)
}
}
async function setActiveOrganization(organizationId: string) {
try {
const { data: activeOrganizationToSet } = await organizationApi.setActiveOrganization(organizationId)
activeOrganization.value = activeOrganizationToSet
const { data: invitationsToSet } = await organizationApi.listInvitations(activeOrganizationToSet?.id)
invitations.value = invitationsToSet ?? []
} catch (e) {
toast.add({ title: 'Error setting active organizations', color: 'error' })
console.error('Error setting active organizations:', e)
}
}
return {
activeOrganization,
organizations,
createOrganization,
deleteOrganization,
invitations,
getInvitation,
loadInvitations,
inviteMember,
acceptInvitation,
rejectInvitation,
cancelSentInvitation,
loadOrganizations,
setActiveOrganization
}
})