import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query' import type { Ref } from 'vue' import { apiClient } from '@/lib/axios' import type { AcceptInvitationPayload, AcceptInvitationResponse, InvitationDetailResponse, InviteMemberPayload, Member, MemberListResponse, MemberScope, UpdateMemberRolePayload, } from '@/types/member' interface ApiResponse { success: boolean data: T message?: string } function memberListKey(scope: MemberScope, orgId: Ref) { return ['members', scope, orgId] as const } function invalidateScopedKeys(scope: MemberScope, orgId: Ref, queryClient: ReturnType) { queryClient.invalidateQueries({ queryKey: memberListKey(scope, orgId) }) if (scope === 'platform') queryClient.invalidateQueries({ queryKey: ['admin', 'organisations', orgId] }) } function endpointList(scope: MemberScope, orgId: string) { return scope === 'platform' ? `/admin/organisations/${orgId}` : `/organisations/${orgId}/members` } function endpointInvite(scope: MemberScope, orgId: string) { return scope === 'platform' ? `/admin/organisations/${orgId}/invite` : `/organisations/${orgId}/invite` } function endpointMember(scope: MemberScope, orgId: string, userId: string) { return scope === 'platform' ? `/admin/organisations/${orgId}/members/${userId}` : `/organisations/${orgId}/members/${userId}` } export function useMembersList(scope: MemberScope, orgId: Ref) { return useQuery({ queryKey: memberListKey(scope, orgId), queryFn: async () => { const url = endpointList(scope, orgId.value) if (scope === 'platform') { const { data } = await apiClient.get>(url) return { data: data.data.members, meta: { total_members: data.data.members.length, pending_invitations_count: 0, pending_invitations: [], }, } satisfies MemberListResponse } const { data } = await apiClient.get(url) return data }, enabled: () => !!orgId.value, }) } export function useInviteMember(scope: MemberScope, orgId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async (payload: InviteMemberPayload) => { const { data } = await apiClient.post>(endpointInvite(scope, orgId.value), payload) return data.data }, onSuccess: () => invalidateScopedKeys(scope, orgId, queryClient), }) } export function useUpdateMemberRole(scope: MemberScope, orgId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async ({ userId, role }: UpdateMemberRolePayload) => { const { data } = await apiClient.put>( endpointMember(scope, orgId.value, userId), { role }, ) return data.data }, onSuccess: () => invalidateScopedKeys(scope, orgId, queryClient), }) } export function useRemoveMember(scope: MemberScope, orgId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async (userId: string) => { await apiClient.delete(endpointMember(scope, orgId.value, userId)) }, onSuccess: () => invalidateScopedKeys(scope, orgId, queryClient), }) } export function useRevokeInvitation(orgId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async (invitationId: string) => { await apiClient.delete(`/organisations/${orgId.value}/invitations/${invitationId}`) }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: memberListKey('organisation', orgId) }) }, }) } export function useInvitationDetail(token: Ref) { return useQuery({ queryKey: ['invitation', token], queryFn: async () => { const { data } = await apiClient.get>(`/invitations/${token.value}`) return data.data }, enabled: () => !!token.value, retry: false, }) } export function useAcceptInvitation() { return useMutation({ mutationFn: async ({ token, ...payload }: AcceptInvitationPayload & { token: string }) => { const { data } = await apiClient.post(`/invitations/${token}/accept`, payload) return data }, }) }