// eveai_chat_client/static/assets/js/composables/useContentModal.js import { ref, reactive, provide, inject } from 'vue'; // Injection key for the composable export const CONTENT_MODAL_KEY = Symbol('contentModal'); // Create the composable export function useContentModal() { // Reactive state for modal const modalState = reactive({ show: false, title: '', content: '', version: '', loading: false, error: false, errorMessage: '', lastContentUrl: '' // Add this for retry functionality }); // Content cache to avoid repeated API calls const contentCache = ref({}); // Show modal with content const showModal = async (options = {}) => { const { title = 'Content', contentUrl = null, content = null, version = '' } = options; // Set initial state modalState.show = true; modalState.title = title; modalState.content = content || ''; modalState.version = version; modalState.loading = !!contentUrl; // Only show loading if we need to fetch content modalState.error = false; modalState.errorMessage = ''; modalState.lastContentUrl = contentUrl || ''; // Store for retry functionality // If content is provided directly, no need to fetch if (content) { modalState.loading = false; return; } // If contentUrl is provided, fetch the content if (contentUrl) { await loadContent(contentUrl); } }; // Hide modal const hideModal = () => { console.log('Hiding content modal'); modalState.show = false; modalState.title = ''; modalState.content = ''; modalState.version = ''; modalState.loading = false; modalState.error = false; modalState.errorMessage = ''; modalState.lastContentUrl = ''; // Clear for next use }; // Load content from API const loadContent = async (contentUrl) => { try { console.log('Loading content from:', contentUrl); modalState.loading = true; modalState.error = false; modalState.errorMessage = ''; // Check cache first if (contentCache.value[contentUrl]) { console.log('Content found in cache for:', contentUrl); const cached = contentCache.value[contentUrl]; modalState.content = cached.content; modalState.version = cached.version; modalState.loading = false; return; } // Fetch from API console.log('Fetching content from API:', contentUrl); const response = await fetch(contentUrl); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); console.log('API response received:', { hasSuccess: data.success !== undefined, hasContent: data.content !== undefined, hasError: data.error !== undefined, contentLength: data.content ? data.content.length : 0 }); // Support both response formats if (data.success !== undefined) { // New format with success property if (data.success) { modalState.content = data.content || ''; modalState.version = data.version || ''; } else { throw new Error(data.error || 'Onbekende fout bij het laden van content'); } } else if (data.content !== undefined) { // Legacy format without success property (current dpa/terms endpoints) modalState.content = data.content || ''; modalState.version = data.version || ''; } else if (data.error) { // Error response format throw new Error(data.message || data.error || 'Er is een fout opgetreden'); } else { throw new Error('Invalid response format: no content or success property found'); } // Cache the result contentCache.value[contentUrl] = { content: modalState.content, version: modalState.version, timestamp: Date.now() }; } catch (error) { console.error('Error loading content:', error); modalState.error = true; modalState.errorMessage = error.message || 'Er is een fout opgetreden bij het laden van de content.'; } finally { modalState.loading = false; } }; // Retry loading content const retryLoad = async () => { if (modalState.lastContentUrl) { console.log('Retrying content load for:', modalState.lastContentUrl); await loadContent(modalState.lastContentUrl); } else { console.warn('No content URL available for retry'); modalState.error = true; modalState.errorMessage = 'Geen content URL beschikbaar voor opnieuw proberen.'; } }; // Clear cache (useful for development or when content updates) const clearCache = () => { contentCache.value = {}; }; // Get cache size for debugging const getCacheInfo = () => { return { size: Object.keys(contentCache.value).length, entries: Object.keys(contentCache.value) }; }; return { // State modalState, // Methods showModal, hideModal, loadContent, retryLoad, clearCache, getCacheInfo }; } // Provider function to be used in the root component export function provideContentModal() { const contentModal = useContentModal(); provide(CONTENT_MODAL_KEY, contentModal); return contentModal; } // Injector function to be used in child components export function injectContentModal() { const contentModal = inject(CONTENT_MODAL_KEY); if (!contentModal) { throw new Error('useContentModal must be provided before it can be injected'); } return contentModal; }