evOo-local/packages/core/src/bot-sections.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

66 lines
1.9 KiB
TypeScript

export type BotListSection<T> = {
key: string;
title: string | null;
bots: T[];
};
type Section = { id: string; name: string };
type SectionedBot = { pinned: boolean; sectionId: string | null };
export function groupBotsForSidebar<T extends SectionedBot>(
bots: readonly T[],
sections: readonly Section[],
): BotListSection<T>[] {
const knownSectionIds = new Set(sections.map((section) => section.id));
const pinned: T[] = [];
const sectionMembers = new Map<string, T[]>();
const unassigned: T[] = [];
const grouped: BotListSection<T>[] = [];
for (const bot of bots) {
if (bot.pinned) {
pinned.push(bot);
} else if (bot.sectionId && knownSectionIds.has(bot.sectionId)) {
const members = sectionMembers.get(bot.sectionId) ?? [];
members.push(bot);
sectionMembers.set(bot.sectionId, members);
} else {
unassigned.push(bot);
}
}
if (pinned.length > 0) {
grouped.push({ key: "pinned", title: "Pinned", bots: pinned });
}
for (const section of sections) {
const members = sectionMembers.get(section.id) ?? [];
if (members.length > 0) {
grouped.push({ key: `section:${section.id}`, title: section.name, bots: members });
}
}
if (unassigned.length > 0) {
grouped.push({
key: "unassigned",
title: pinned.length > 0 || sections.length > 0 ? "Unassigned" : null,
bots: unassigned,
});
}
return grouped;
}
export function reorderBotTo<T extends { id: string }>(
bots: readonly T[],
sourceId: string,
targetId: string,
): readonly T[] {
const sourceIndex = bots.findIndex((bot) => bot.id === sourceId);
const targetIndex = bots.findIndex((bot) => bot.id === targetId);
if (sourceIndex < 0 || targetIndex < 0 || sourceIndex === targetIndex) return bots;
const reordered = [...bots];
const [source] = reordered.splice(sourceIndex, 1);
if (!source) return bots;
reordered.splice(targetIndex, 0, source);
return reordered;
}