mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
99 lines
3.3 KiB
TypeScript
99 lines
3.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;
|
|
// Get sector name - try .name path first, then fallback to object extraction
|
|
let sectorName = t(`${sector.nameKey}.name`);
|
|
// If translation returned the key itself (not found), try accessing the object directly
|
|
if (sectorName === `${sector.nameKey}.name` || !sectorName) {
|
|
// The t() function should automatically extract .name from objects, but if that fails,
|
|
// try getting the raw translation and extracting name manually
|
|
const rawTranslation = t(sector.nameKey);
|
|
if (rawTranslation && rawTranslation !== sector.nameKey) {
|
|
sectorName = rawTranslation;
|
|
} else {
|
|
// Final fallback: extract readable name from key (e.g., "sectors.construction" -> "Construction")
|
|
const keyPart = sector.nameKey.replace('sectors.', '');
|
|
sectorName = keyPart.charAt(0).toUpperCase() + keyPart.slice(1).replace(/_/g, ' ');
|
|
}
|
|
}
|
|
return {
|
|
id: sector.nameKey,
|
|
label: sectorName,
|
|
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];
|
|
|
|
// Safely check for connections with null/undefined guards
|
|
const orgAOffers = orgA.offers || [];
|
|
const orgANeeds = orgA.needs || [];
|
|
const orgBOffers = orgB.offers || [];
|
|
const orgBNeeds = orgB.needs || [];
|
|
|
|
const hasConnection =
|
|
orgAOffers.some((o) =>
|
|
orgBNeeds.some((n) => n.resource.toLowerCase().includes(o.resource.toLowerCase()))
|
|
) ||
|
|
orgBOffers.some((o) =>
|
|
orgANeeds.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 };
|
|
};
|