turash/bugulma/frontend/hooks/useDirectSymbiosis.ts
Damir Mukimov 6347f42e20
Consolidate repositories: Remove nested frontend .git and merge into main repository
- Remove nested git repository from bugulma/frontend/.git
- Add all frontend files to main repository tracking
- Convert from separate frontend/backend repos to unified monorepo
- Preserve all frontend code and development history as tracked files
- Eliminate nested repository complexity for simpler development workflow

This creates a proper monorepo structure with frontend and backend
coexisting in the same repository for easier development and deployment.
2025-11-25 06:02:57 +01:00

75 lines
2.6 KiB
TypeScript

import { useMemo } from 'react';
import { canParticipateInResourceMatching } from '@/schemas/organizationSubtype.ts';
import type { Organization } from '@/types.ts';
import { useDirectSymbiosis as useDirectSymbiosisAPI } from '@/hooks/api/useDirectSymbiosisAPI.ts';
import { useOrganizations } from '@/hooks/useOrganizations.ts';
interface Match {
partner: Organization;
resource: string;
}
/**
* Get direct symbiosis matches for an organization
* Uses backend API to get matches based on ResourceFlows
* Only commercial organizations participate in resource matching
*/
export const useDirectSymbiosis = (
organization: Organization | null
): { providers: Match[]; consumers: Match[]; isLoading: boolean; error: Error | null } => {
const { organizations: allOrganizations } = useOrganizations();
// Only fetch matches if organization is commercial
const canMatch = organization ? canParticipateInResourceMatching(organization.Subtype) : false;
const { data, isLoading, error } = useDirectSymbiosisAPI(canMatch ? organization?.ID : undefined);
// Memoize organization map for O(1) lookup instead of O(n) find
const orgMap = useMemo(() => {
if (!allOrganizations || !Array.isArray(allOrganizations))
return new Map<string, Organization>();
return new Map(allOrganizations.map((org) => [org.ID, org]));
}, [allOrganizations]);
// Map backend response to frontend format
// Filter to only include commercial organizations
// Memoize to prevent recalculation on every render
const providers: Match[] = useMemo(() => {
if (!data?.providers || !Array.isArray(data.providers)) return [];
return data.providers
.map((match) => {
const partner = orgMap.get(match.partner_id);
if (!partner || !canParticipateInResourceMatching(partner.Subtype)) {
return null;
}
return {
partner,
resource: match.resource,
};
})
.filter((match): match is Match => match !== null);
}, [data, orgMap]);
const consumers: Match[] = useMemo(() => {
if (!data?.consumers || !Array.isArray(data.consumers)) return [];
return data.consumers
.map((match) => {
const partner = orgMap.get(match.partner_id);
if (!partner || !canParticipateInResourceMatching(partner.Subtype)) {
return null;
}
return {
partner,
resource: match.resource,
};
})
.filter((match): match is Match => match !== null);
}, [data, orgMap]);
return {
providers,
consumers,
isLoading,
error: error instanceof Error ? error : null,
};
};