turash/bugulma/frontend/lib/graphUtils.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

79 lines
2.3 KiB
TypeScript

import { SECTORS } from '@/constants.tsx';
import { Organization } from '@/types.ts';
export interface GraphNode {
id: string;
label: string;
x: number;
y: number;
color: string;
size: number;
orgCount: number;
}
export interface GraphLink {
source: string;
target: string;
value: number;
}
export const generateGraphData = (
organizations: Organization[],
t: (key: string) => string
): { nodes: GraphNode[]; links: GraphLink[] } => {
const sectorMap = new Map<string, string[]>(); // Map sector nameKey to org IDs
SECTORS.forEach((s) => sectorMap.set(s.nameKey, []));
organizations.forEach((org) => {
if (sectorMap.has(org.sector)) {
sectorMap.get(org.sector)!.push(org.id);
}
});
// Create nodes
const angleStep = (2 * Math.PI) / SECTORS.length;
const radius = 150;
const nodes: GraphNode[] = SECTORS.map((sector, i) => {
const orgCount = sectorMap.get(sector.nameKey)!.length;
const sectorName = t(`${sector.nameKey}.name`);
return {
id: sector.nameKey,
label: typeof sectorName === 'string' ? sectorName : sector.nameKey,
x: 200 + radius * Math.cos(angleStep * i - Math.PI / 2),
y: 200 + radius * Math.sin(angleStep * i - Math.PI / 2),
color: sector.colorKey,
size: Math.max(10, (orgCount || 0) * 2),
orgCount: orgCount,
};
});
// Create links
const linksMap = new Map<string, number>(); // key: "source-target"
for (let i = 0; i < organizations.length; i++) {
for (let j = i + 1; j < organizations.length; j++) {
const orgA = organizations[i];
const orgB = organizations[j];
const hasConnection =
orgA.offers.some((o) =>
orgB.needs.some((n) => n.resource.toLowerCase().includes(o.resource.toLowerCase()))
) ||
orgB.offers.some((o) =>
orgA.needs.some((n) => n.resource.toLowerCase().includes(o.resource.toLowerCase()))
);
if (hasConnection && orgA.sector !== orgB.sector) {
const linkKey = [orgA.sector, orgB.sector].sort().join('-');
linksMap.set(linkKey, (linksMap.get(linkKey) || 0) + 1);
}
}
}
const links: GraphLink[] = Array.from(linksMap.entries()).map(([key, value]) => {
const [source, target] = key.split('-');
return { source, target, value };
});
return { nodes, links };
};