import { BaseService } from '@/core/base/BaseService' import { toast } from 'vue-sonner' // Define our own ToastOptions interface based on vue-sonner's common options interface ToastOptions { duration?: number position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center' richColors?: boolean closeButton?: boolean description?: string action?: { label: string onClick: () => void } cancel?: { label: string onClick?: () => void } id?: string dismissible?: boolean onDismiss?: () => void onAutoClose?: () => void } /** * Toast notification configuration */ interface ToastConfig { duration: number position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center' richColors: boolean closeButton: boolean } /** * Predefined toast action types with consistent styling */ export enum ToastActionType { SUCCESS = 'success', ERROR = 'error', WARNING = 'warning', INFO = 'info', LOADING = 'loading' } /** * Context-specific toast message templates */ interface ToastContext { auth: { loginSuccess: string loginError: string logoutSuccess: string registrationSuccess: string registrationError: string } payment: { processing: string success: string failed: string copied: string copyFailed: string } clipboard: { copied: string copyFailed: string } general: { operationSuccess: string operationFailed: string loading: string } } /** * Centralized Toast Service providing standardized notifications * Eliminates duplicate import patterns and ensures consistent styling */ export class ToastService extends BaseService { // Service metadata protected readonly metadata = { name: 'ToastService', version: '1.0.0', dependencies: [] // No dependencies } private config: ToastConfig = { duration: 4000, position: 'top-right', richColors: true, closeButton: false } private context: ToastContext = { auth: { loginSuccess: 'Login successful!', loginError: 'Login failed. Please check your credentials.', logoutSuccess: 'Logged out successfully', registrationSuccess: 'Registration successful!', registrationError: 'Registration failed. Please try again.' }, payment: { processing: 'Processing payment...', success: 'Payment successful!', failed: 'Payment failed', copied: 'Payment request copied to clipboard', copyFailed: 'Failed to copy payment request' }, clipboard: { copied: 'Copied to clipboard!', copyFailed: 'Failed to copy to clipboard' }, general: { operationSuccess: 'Operation completed successfully', operationFailed: 'Operation failed', loading: 'Loading...' } } /** * Service initialization */ protected async onInitialize(): Promise { this.debug('ToastService initialized') } /** * Show success toast */ success(message: string, options?: Partial): void { toast.success(message, { duration: this.config.duration, ...options }) } /** * Show error toast */ error(message: string, options?: Partial): void { toast.error(message, { duration: this.config.duration, ...options }) } /** * Show info toast */ info(message: string, options?: Partial): void { toast.info(message, { duration: this.config.duration, ...options }) } /** * Show warning toast */ warning(message: string, options?: Partial): void { toast.warning(message, { duration: this.config.duration, ...options }) } /** * Show loading toast */ loading(message: string, options?: Partial): string | number { return toast.loading(message, { duration: Infinity, // Loading toasts don't auto-dismiss ...options }) } /** * Dismiss a specific toast */ dismiss(toastId?: string | number): void { toast.dismiss(toastId) } /** * Context-specific toast methods */ // Authentication toasts auth = { loginSuccess: (options?: Partial) => this.success(this.context.auth.loginSuccess, options), loginError: (error?: string, options?: Partial) => this.error(error || this.context.auth.loginError, options), logoutSuccess: (options?: Partial) => this.success(this.context.auth.logoutSuccess, options), registrationSuccess: (options?: Partial) => this.success(this.context.auth.registrationSuccess, options), registrationError: (error?: string, options?: Partial) => this.error(error || this.context.auth.registrationError, options) } // Payment toasts payment = { processing: (options?: Partial) => this.loading(this.context.payment.processing, options), success: (message?: string, options?: Partial) => this.success(message || this.context.payment.success, options), failed: (error?: string, options?: Partial) => this.error(error || this.context.payment.failed, options), copied: (options?: Partial) => this.success(this.context.payment.copied, options), copyFailed: (options?: Partial) => this.error(this.context.payment.copyFailed, options) } // Clipboard toasts clipboard = { copied: (item?: string, options?: Partial) => this.success(item ? `${item} copied to clipboard!` : this.context.clipboard.copied, options), copyFailed: (item?: string, options?: Partial) => this.error(item ? `Failed to copy ${item}` : this.context.clipboard.copyFailed, options) } // General operation toasts operation = { success: (message?: string, options?: Partial) => this.success(message || this.context.general.operationSuccess, options), failed: (error?: string, options?: Partial) => this.error(error || this.context.general.operationFailed, options), loading: (message?: string, options?: Partial) => this.loading(message || this.context.general.loading, options) } /** * Create a toast for async operations with auto-updating states */ async asyncOperation( operation: Promise, messages: { loading?: string success?: string | ((result: T) => string) error?: string | ((error: Error) => string) }, options?: Partial ): Promise { const loadingToast = this.loading(messages.loading || 'Processing...', options) try { const result = await operation this.dismiss(loadingToast) const successMessage = typeof messages.success === 'function' ? messages.success(result) : messages.success || 'Operation successful!' this.success(successMessage, options) return result } catch (error) { this.dismiss(loadingToast) const errorMessage = typeof messages.error === 'function' ? messages.error(error as Error) : messages.error || (error as Error).message || 'Operation failed' this.error(errorMessage, options) throw error } } /** * Update toast configuration */ updateConfig(newConfig: Partial): void { this.config = { ...this.config, ...newConfig } } /** * Update context messages */ updateContext(newContext: Partial): void { this.context = { auth: { ...this.context.auth, ...newContext.auth }, payment: { ...this.context.payment, ...newContext.payment }, clipboard: { ...this.context.clipboard, ...newContext.clipboard }, general: { ...this.context.general, ...newContext.general } } } } // Export singleton instance export const toastService = new ToastService()