/** * Enhanced API wrapper with integrated error handling and notifications * * This example shows how to use the error store and notification system together * to provide comprehensive error handling and user feedback for API calls. */ import { useErrorStore } from "@/stores/errors"; import { useNotificationStore } from "@/stores/notifications"; import { useLoadingStore } from "@/stores/loading"; import Api from "./api"; export class ApiWithErrorHandling { static async makeApiCall(apiFunction, options = {}) { const { // Error handling options componentName = null, showErrorNotifications = true, showSuccessNotifications = true, // Loading options showLoading = true, loadingMessage = "Loading...", // Success options successMessage = null, successTitle = "Success", // Error options errorTitle = "Error", customErrorMessage = null, // Retry options retryCount = 0, retryDelay = 1000, // Operation identifier for tracking operationKey = null, } = options; const errorStore = useErrorStore(); const notificationStore = useNotificationStore(); const loadingStore = useLoadingStore(); // Generate operation key if not provided const operation = operationKey || `api-${Date.now()}`; try { // Clear any existing errors if (componentName) { errorStore.clearComponentError(componentName); } // Show loading state if (showLoading) { if (componentName) { loadingStore.setComponentLoading(componentName, true, loadingMessage); } else { loadingStore.startOperation(operation, loadingMessage); } } // Make the API call with retry logic const result = await errorStore.handleApiCall(operation, apiFunction, { showNotification: showErrorNotifications, retryCount, retryDelay, }); // Show success notification if (showSuccessNotifications && successMessage) { notificationStore.addSuccess(successMessage, successTitle); } return result; } catch (error) { // The error store has already handled the error notification // But we can add custom handling here if needed console.error("API call failed:", error); // Optionally show a custom error message if (customErrorMessage && !showErrorNotifications) { notificationStore.addError(customErrorMessage, errorTitle); } // Re-throw the error so calling code can handle it if needed throw error; } finally { // Always clear loading state if (showLoading) { if (componentName) { loadingStore.setComponentLoading(componentName, false); } else { loadingStore.stopOperation(operation); } } } } // Convenience methods for common API operations static async getClientStatusCounts(options = {}) { return this.makeApiCall(() => Api.getClientStatusCounts(), { operationKey: "client-status-counts", componentName: "clients", loadingMessage: "Loading client status data...", successMessage: null, // Don't show success for data fetches ...options, }); } static async getPaginatedClientDetails(paginationParams, filters, sorting, options = {}) { return this.makeApiCall( () => Api.getPaginatedClientDetails(paginationParams, filters, sorting), { operationKey: "client-table-data", componentName: "dataTable", loadingMessage: "Loading client data...", successMessage: null, // Don't show success for data fetches ...options, }, ); } static async createClient(clientData, options = {}) { return this.makeApiCall(() => Api.createClient(clientData), { operationKey: "create-client", componentName: "form", loadingMessage: "Creating client...", successMessage: "Client created successfully!", errorTitle: "Failed to Create Client", ...options, }); } static async getPaginatedJobDetails(paginationParams, filters, sorting, options = {}) { return this.makeApiCall( () => Api.getPaginatedJobDetails(paginationParams, filters, sorting), { operationKey: "job-table-data", componentName: "jobs", loadingMessage: "Loading job data...", successMessage: null, ...options, }, ); } static async getPaginatedWarrantyData(paginationParams, filters, sorting, options = {}) { return this.makeApiCall( () => Api.getPaginatedWarrantyData(paginationParams, filters, sorting), { operationKey: "warranty-table-data", componentName: "warranties", loadingMessage: "Loading warranty data...", successMessage: null, ...options, }, ); } static async getCityStateByZip(zipcode, options = {}) { return this.makeApiCall(() => Api.getCityStateByZip(zipcode), { operationKey: "zip-lookup", componentName: "form", loadingMessage: "Looking up location...", successMessage: null, errorTitle: "Zip Code Lookup Failed", customErrorMessage: "Unable to find location for the provided zip code", retryCount: 2, retryDelay: 1000, ...options, }); } } /** * Example usage in Vue components: * * */ export default ApiWithErrorHandling;