/** * TT-Core Async Data Composable (Vue 3) * Provides async data fetching with loading states */ /** * Create an async data composable * @returns {Object} - Composable with state and methods */ export function useAsyncData() { const { ref } = Vue; const isLoading = ref(false); const hasError = ref(false); const errorMessage = ref(null); const data = ref(null); /** * Execute async operation with loading state * @param {Function} asyncFn - Async function to execute * @param {Object} options - Options * @returns {Promise} - Result */ const executeAsync = async (asyncFn, options = {}) => { isLoading.value = true; hasError.value = false; errorMessage.value = null; try { const result = await asyncFn(); data.value = result; return result; } catch (error) { hasError.value = true; errorMessage.value = error.message || 'Ein Fehler ist aufgetreten'; if (options.onError) { options.onError(error); } throw error; } finally { isLoading.value = false; } }; /** * Fetch data from API * @param {string} url - API URL * @param {Object} options - Fetch options * @returns {Promise} - Response data */ const fetchData = async (url, options = {}) => { return executeAsync(async () => { const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } return await response.text(); }); }; /** * Reset state */ const reset = () => { isLoading.value = false; hasError.value = false; errorMessage.value = null; data.value = null; }; return { isLoading, hasError, errorMessage, data, executeAsync, fetchData, reset }; } /** * Create an async data mixin (backward compatibility) * @returns {Object} - Vue mixin */ export function createAsyncDataMixin() { return { data() { return { isLoading: false, hasError: false, errorMessage: null }; }, methods: { /** * Execute async operation with loading state * @param {Function} asyncFn - Async function to execute * @param {Object} options - Options * @returns {Promise} - Result */ async executeAsync(asyncFn, options = {}) { this.isLoading = true; this.hasError = false; this.errorMessage = null; try { const result = await asyncFn(); return result; } catch (error) { this.hasError = true; this.errorMessage = error.message || 'Ein Fehler ist aufgetreten'; if (options.onError) { options.onError(error); } throw error; } finally { this.isLoading = false; } }, /** * Fetch data from API * @param {string} url - API URL * @param {Object} options - Fetch options * @returns {Promise} - Response data */ async fetchData(url, options = {}) { return this.executeAsync(async () => { const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } return await response.text(); }); } } }; }