turash/bugulma/frontend/hooks/api/useOrganizationsAPI.ts
2025-12-15 10:06:41 +01:00

103 lines
3.4 KiB
TypeScript

import { useAuth } from '@/contexts/AuthContext';
import {
commonQueryOptions,
createDetailQueryHook,
createListQueryHook,
useInvalidatingMutation,
} from '@/lib/api-hooks';
import { createQueryKeyFactory } from '@/lib/query-keys';
import type { CreateOrganizationRequest } from '@/schemas/backend/organization';
import { getOrganizationById, getOrganizations } from '@/services/organization-service';
import {
createOrganization,
deleteOrganization,
getUserOrganizations,
updateOrganization,
} from '@/services/organizations-api';
import { useQuery } from '@tanstack/react-query';
/**
* Query key factory for organizations
* Uses reusable factory to reduce duplication
* Version 2: Fixed JSON array serialization in backend
*/
const baseKeys = createQueryKeyFactory('organizations');
export const organizationKeys = {
...baseKeys,
// Override methods to include version for cache invalidation
lists: () => [...baseKeys.lists(), 'v2'] as const,
list: (filters?: Record<string, unknown>) => [...baseKeys.list(filters), 'v2'] as const,
details: () => [...baseKeys.details(), 'v2'] as const,
detail: (id: string) => [...baseKeys.detail(id), 'v2'] as const,
user: () => [...baseKeys.all, 'user', 'v2'] as const,
};
/**
* Hook to fetch all organizations
* Uses generic factory for consistent behavior
*/
export const useOrganizations = createListQueryHook(organizationKeys.lists(), getOrganizations);
/**
* Hook to fetch a single organization by ID
* Uses generic factory for consistent behavior
*/
export const useOrganization = createDetailQueryHook(
(id) => organizationKeys.detail(id!),
(id) => getOrganizationById(id)
);
/**
* Hook to create a new organization
* Uses reusable mutation utility for consistent invalidation
*/
export function useCreateOrganization() {
return useInvalidatingMutation({
mutationFn: (request: CreateOrganizationRequest) => createOrganization(request),
invalidateKeys: [organizationKeys.lists()],
});
}
/**
* Hook to delete an organization
* Uses reusable mutation utility for consistent invalidation
*/
export function useDeleteOrganization() {
return useInvalidatingMutation({
mutationFn: (id: string) => deleteOrganization(id),
invalidateKeys: [organizationKeys.lists(), organizationKeys.user()],
});
}
/**
* Hook to update an organization
* Accepts payload: { id: string, data: Partial<CreateOrganizationRequest> }
*/
export function useUpdateOrganization() {
return useInvalidatingMutation({
mutationFn: (payload: { id: string; data: Partial<CreateOrganizationRequest> }) =>
updateOrganization(payload.id, payload.data),
// Invalidate lists and details caches so both listings and detail pages refresh
invalidateKeys: [organizationKeys.lists(), organizationKeys.details()],
});
}
/**
* Hook to fetch organizations for the current user
* Only enabled when user is authenticated to avoid 401 errors
*/
export function useUserOrganizations() {
const { isAuthenticated, isLoading } = useAuth();
console.log('[useUserOrganizations] isAuthenticated:', isAuthenticated, 'isLoading:', isLoading);
return useQuery({
queryKey: organizationKeys.user(),
queryFn: getUserOrganizations,
enabled: isAuthenticated && !isLoading,
staleTime: commonQueryOptions.standardStaleTime,
placeholderData: () =>
[] as ReturnType<typeof getUserOrganizations> extends Promise<infer T> ? T : never,
});
}