UNPKG

@churchapps/helpers

Version:

Library of helper functions not specific to any one ChurchApps project or framework.

108 lines 4 kB
import { LessonsContentProvider } from "./contentProviders/LessonsContentProvider.js"; export class PlanHelper { static providers = [new LessonsContentProvider()]; // Register additional content providers static registerProvider(provider) { // Avoid duplicates if (!this.providers.find(p => p.providerId === provider.providerId)) { this.providers.push(provider); } } // Replace a provider (useful for configuring with different URLs) static replaceProvider(provider) { const index = this.providers.findIndex(p => p.providerId === provider.providerId); if (index >= 0) { this.providers[index] = provider; } else { this.providers.push(provider); } } // Main method: populate planItems with their content static async populate(plan, planItems) { // Flatten hierarchy to get all items const allItems = this.flattenItems(planItems); // Group items by provider const itemsByProvider = new Map(); for (const item of allItems) { for (const provider of this.providers) { if (provider.canHandle(plan, item)) { const existing = itemsByProvider.get(provider) || []; existing.push(item); itemsByProvider.set(provider, existing); break; // First matching provider wins } } } // Fetch content from each provider in parallel const fetchPromises = []; const contentMap = new Map(); for (const [provider, items] of itemsByProvider) { fetchPromises.push(provider.fetchContent(plan, items).then(providerContent => { for (const [itemId, content] of providerContent) { contentMap.set(itemId, content); } })); } await Promise.all(fetchPromises); // Attach content to items (mutates in place for efficiency) this.attachContent(planItems, contentMap); return planItems; } // Flatten nested planItems for processing static flattenItems(items) { const result = []; const collect = (itemList) => { for (const item of itemList) { result.push(item); if (item.children?.length) { collect(item.children); } } }; collect(items); return result; } // Attach content to items recursively static attachContent(items, contentMap) { for (const item of items) { const content = contentMap.get(item.id); if (content) { item.content = content; } if (item.children?.length) { this.attachContent(item.children, contentMap); } } } // Convenience: Get the lessons provider for direct lesson operations static getLessonsProvider() { return this.providers.find(p => p.providerId === "lessons"); } // ============================================ // Time Formatting Utilities // ============================================ /** * Format seconds as MM:SS string * @param seconds - Number of seconds to format * @returns Formatted time string (e.g., "3:45") */ static formatTime(seconds) { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return mins + ":" + (secs < 10 ? "0" : "") + secs; } /** * Calculate total duration of a section's children * @param section - PlanItem with children * @returns Total seconds from all children */ static getSectionDuration(section) { let totalSeconds = 0; section.children?.forEach((child) => { totalSeconds += child.seconds || 0; }); return totalSeconds; } } //# sourceMappingURL=PlanHelper.js.map