Browse Source
Created notification utility approaches to consolidate verbose $notify calls: - Simple function utility (src/utils/notify.ts) - recommended approach - Vue 3 composable (src/composables/useNotifications.ts) - Utility class with mixin (src/utils/notificationUtils.ts) Updated ClaimView.vue to demonstrate usage, reducing notification code by ~70%. Enhanced PlatformServiceMixin with improved caching and database methods. Updated ShareMyContactInfoView.vue with mixin improvements. Provides consistent timeouts, standardized patterns, and type safety. Ready for migration alongside mixin updates.pull/142/head
6 changed files with 683 additions and 188 deletions
@ -0,0 +1,140 @@ |
|||||
|
import { inject } from 'vue'; |
||||
|
import { NotificationIface } from '../constants/app'; |
||||
|
|
||||
|
/** |
||||
|
* Vue 3 composable for notifications |
||||
|
* Provides a concise API for common notification patterns |
||||
|
*/ |
||||
|
|
||||
|
export const NOTIFICATION_TIMEOUTS = { |
||||
|
BRIEF: 1000, // Very brief toasts ("Sent..." messages)
|
||||
|
SHORT: 2000, // Short notifications (clipboard copies, quick confirmations)
|
||||
|
STANDARD: 3000, // Standard notifications (success messages, general info)
|
||||
|
LONG: 5000, // Longer notifications (errors, warnings, important info)
|
||||
|
VERY_LONG: 7000, // Very long notifications (complex operations)
|
||||
|
MODAL: -1, // Modal confirmations (no auto-dismiss)
|
||||
|
} as const; |
||||
|
|
||||
|
export function useNotifications() { |
||||
|
// Inject the notify function from the app
|
||||
|
const notify = inject<(notification: NotificationIface, timeout?: number) => void>('$notify'); |
||||
|
|
||||
|
if (!notify) { |
||||
|
throw new Error('useNotifications must be used within a component that has $notify available'); |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
// Direct access to the original notify function
|
||||
|
notify, |
||||
|
|
||||
|
// Success notifications
|
||||
|
success: (text: string, timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: "Success", |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Error notifications
|
||||
|
error: (text: string, timeout = NOTIFICATION_TIMEOUTS.LONG) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "danger", |
||||
|
title: "Error", |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Warning notifications
|
||||
|
warning: (text: string, timeout = NOTIFICATION_TIMEOUTS.LONG) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "warning", |
||||
|
title: "Warning", |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Info notifications
|
||||
|
info: (text: string, timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: "Info", |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Toast notifications (brief)
|
||||
|
toast: (title: string, text?: string, timeout = NOTIFICATION_TIMEOUTS.BRIEF) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title, |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Clipboard copy notifications
|
||||
|
copied: (item: string, timeout = NOTIFICATION_TIMEOUTS.SHORT) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title: "Copied", |
||||
|
text: `${item} was copied to the clipboard.`, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Sent brief notification
|
||||
|
sent: (timeout = NOTIFICATION_TIMEOUTS.BRIEF) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title: "Sent...", |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Confirmation modal
|
||||
|
confirm: (text: string, onYes: () => Promise<void>, timeout = NOTIFICATION_TIMEOUTS.MODAL) => { |
||||
|
notify({ |
||||
|
group: "modal", |
||||
|
type: "confirm", |
||||
|
title: "Confirm", |
||||
|
text, |
||||
|
onYes, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Standard confirmation messages
|
||||
|
confirmationSubmitted: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: "Success", |
||||
|
text: "Confirmation submitted.", |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Common error patterns
|
||||
|
genericError: (timeout = NOTIFICATION_TIMEOUTS.LONG) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "danger", |
||||
|
title: "Error", |
||||
|
text: "Something went wrong.", |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Common success patterns
|
||||
|
genericSuccess: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: "Success", |
||||
|
text: "Operation completed successfully.", |
||||
|
}, timeout); |
||||
|
}, |
||||
|
}; |
||||
|
} |
@ -0,0 +1,223 @@ |
|||||
|
import { NotificationIface } from "../constants/app"; |
||||
|
|
||||
|
/** |
||||
|
* Notification utility methods to reduce code duplication |
||||
|
* and provide consistent notification patterns across the app |
||||
|
*/ |
||||
|
|
||||
|
export interface NotificationHelper { |
||||
|
notify: (notification: NotificationIface, timeout?: number) => void; |
||||
|
success: (text: string, timeout?: number) => void; |
||||
|
error: (text: string, timeout?: number) => void; |
||||
|
warning: (text: string, timeout?: number) => void; |
||||
|
info: (text: string, timeout?: number) => void; |
||||
|
toast: (title: string, text?: string, timeout?: number) => void; |
||||
|
copied: (item: string, timeout?: number) => void; |
||||
|
sent: (timeout?: number) => void; |
||||
|
confirm: (text: string, onYes: () => Promise<void>, timeout?: number) => void; |
||||
|
confirmationSubmitted: (timeout?: number) => void; |
||||
|
alreadyConfirmed: (timeout?: number) => void; |
||||
|
cannotConfirmIssuer: (timeout?: number) => void; |
||||
|
cannotConfirmHidden: (timeout?: number) => void; |
||||
|
notRegistered: (timeout?: number) => void; |
||||
|
notAGive: (timeout?: number) => void; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Standard notification timeouts |
||||
|
*/ |
||||
|
export const NOTIFICATION_TIMEOUTS = { |
||||
|
BRIEF: 1000, // Very brief toasts ("Sent..." messages)
|
||||
|
SHORT: 2000, // Short notifications (clipboard copies, quick confirmations)
|
||||
|
STANDARD: 3000, // Standard notifications (success messages, general info)
|
||||
|
LONG: 5000, // Longer notifications (errors, warnings, important info)
|
||||
|
VERY_LONG: 7000, // Very long notifications (complex operations)
|
||||
|
MODAL: -1, // Modal confirmations (no auto-dismiss)
|
||||
|
} as const; |
||||
|
|
||||
|
/** |
||||
|
* Standard notification titles |
||||
|
*/ |
||||
|
export const NOTIFICATION_TITLES = { |
||||
|
SUCCESS: "Success", |
||||
|
ERROR: "Error", |
||||
|
WARNING: "Warning", |
||||
|
INFO: "Info", |
||||
|
COPIED: "Copied", |
||||
|
SENT: "Sent...", |
||||
|
CONFIRM: "Confirm", |
||||
|
NOT_REGISTERED: "Not Registered", |
||||
|
ALREADY_CONFIRMED: "Already Confirmed", |
||||
|
CANNOT_CONFIRM: "Cannot Confirm", |
||||
|
} as const; |
||||
|
|
||||
|
/** |
||||
|
* Standard notification messages |
||||
|
*/ |
||||
|
export const NOTIFICATION_MESSAGES = { |
||||
|
GENERIC_ERROR: "Something went wrong.", |
||||
|
GENERIC_SUCCESS: "Operation completed successfully.", |
||||
|
CLIPBOARD_COPIED: (item: string) => `${item} was copied to the clipboard.`, |
||||
|
SENT_BRIEF: "Sent...", |
||||
|
CONFIRMATION_SUBMITTED: "Confirmation submitted.", |
||||
|
ALREADY_CONFIRMED: "You already confirmed this claim.", |
||||
|
CANNOT_CONFIRM_ISSUER: "You cannot confirm this because you issued this claim.", |
||||
|
CANNOT_CONFIRM_HIDDEN: "You cannot confirm this because some people are hidden.", |
||||
|
NOT_REGISTERED: "Someone needs to register you before you can confirm.", |
||||
|
NOT_A_GIVE: "This is not a giving action to confirm.", |
||||
|
} as const; |
||||
|
|
||||
|
/** |
||||
|
* Creates a notification helper with utility methods |
||||
|
*/ |
||||
|
export function createNotificationHelper(notifyFn: (notification: NotificationIface, timeout?: number) => void): NotificationHelper { |
||||
|
return { |
||||
|
notify: notifyFn, |
||||
|
|
||||
|
// Success notifications
|
||||
|
success: (text: string, timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: NOTIFICATION_TITLES.SUCCESS, |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Error notifications
|
||||
|
error: (text: string, timeout = NOTIFICATION_TIMEOUTS.LONG) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "danger", |
||||
|
title: NOTIFICATION_TITLES.ERROR, |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Warning notifications
|
||||
|
warning: (text: string, timeout = NOTIFICATION_TIMEOUTS.LONG) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "warning", |
||||
|
title: NOTIFICATION_TITLES.WARNING, |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Info notifications
|
||||
|
info: (text: string, timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: NOTIFICATION_TITLES.INFO, |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Toast notifications (brief)
|
||||
|
toast: (title: string, text?: string, timeout = NOTIFICATION_TIMEOUTS.BRIEF) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title, |
||||
|
text, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Clipboard copy notifications
|
||||
|
copied: (item: string, timeout = NOTIFICATION_TIMEOUTS.SHORT) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title: NOTIFICATION_TITLES.COPIED, |
||||
|
text: NOTIFICATION_MESSAGES.CLIPBOARD_COPIED(item), |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Sent brief notification
|
||||
|
sent: (timeout = NOTIFICATION_TIMEOUTS.BRIEF) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title: NOTIFICATION_TITLES.SENT, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Confirmation modal
|
||||
|
confirm: (text: string, onYes: () => Promise<void>, timeout = NOTIFICATION_TIMEOUTS.MODAL) => { |
||||
|
notifyFn({ |
||||
|
group: "modal", |
||||
|
type: "confirm", |
||||
|
title: NOTIFICATION_TITLES.CONFIRM, |
||||
|
text, |
||||
|
onYes, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
// Standard confirmation messages
|
||||
|
confirmationSubmitted: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: NOTIFICATION_TITLES.SUCCESS, |
||||
|
text: NOTIFICATION_MESSAGES.CONFIRMATION_SUBMITTED, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
alreadyConfirmed: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: NOTIFICATION_TITLES.ALREADY_CONFIRMED, |
||||
|
text: NOTIFICATION_MESSAGES.ALREADY_CONFIRMED, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
cannotConfirmIssuer: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: NOTIFICATION_TITLES.CANNOT_CONFIRM, |
||||
|
text: NOTIFICATION_MESSAGES.CANNOT_CONFIRM_ISSUER, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
cannotConfirmHidden: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: NOTIFICATION_TITLES.CANNOT_CONFIRM, |
||||
|
text: NOTIFICATION_MESSAGES.CANNOT_CONFIRM_HIDDEN, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
notRegistered: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: NOTIFICATION_TITLES.NOT_REGISTERED, |
||||
|
text: NOTIFICATION_MESSAGES.NOT_REGISTERED, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
|
||||
|
notAGive: (timeout = NOTIFICATION_TIMEOUTS.STANDARD) => { |
||||
|
notifyFn({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: NOTIFICATION_TITLES.INFO, |
||||
|
text: NOTIFICATION_MESSAGES.NOT_A_GIVE, |
||||
|
}, timeout); |
||||
|
}, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Vue mixin to add notification helpers to components |
||||
|
*/ |
||||
|
export const NotificationMixin = { |
||||
|
computed: { |
||||
|
$notifyHelper() { |
||||
|
return createNotificationHelper((this as any).$notify); |
||||
|
}, |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,136 @@ |
|||||
|
import { NotificationIface } from '../constants/app'; |
||||
|
|
||||
|
/** |
||||
|
* Simple notification utility functions |
||||
|
* Provides the most concise API for common notification patterns |
||||
|
*/ |
||||
|
|
||||
|
export type NotifyFunction = (notification: NotificationIface, timeout?: number) => void; |
||||
|
|
||||
|
// Standard timeouts
|
||||
|
export const TIMEOUTS = { |
||||
|
BRIEF: 1000, // Very brief toasts ("Sent..." messages)
|
||||
|
SHORT: 2000, // Short notifications (clipboard copies, quick confirmations)
|
||||
|
STANDARD: 3000, // Standard notifications (success messages, general info)
|
||||
|
LONG: 5000, // Longer notifications (errors, warnings, important info)
|
||||
|
VERY_LONG: 7000, // Very long notifications (complex operations)
|
||||
|
MODAL: -1, // Modal confirmations (no auto-dismiss)
|
||||
|
} as const; |
||||
|
|
||||
|
/** |
||||
|
* Create notification helpers for a given notify function |
||||
|
*/ |
||||
|
export function createNotifyHelpers(notify: NotifyFunction) { |
||||
|
return { |
||||
|
// Success notifications
|
||||
|
success: (text: string, timeout?: number) => |
||||
|
notify({ group: "alert", type: "success", title: "Success", text }, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
// Error notifications
|
||||
|
error: (text: string, timeout?: number) => |
||||
|
notify({ group: "alert", type: "danger", title: "Error", text }, timeout || TIMEOUTS.LONG), |
||||
|
|
||||
|
// Warning notifications
|
||||
|
warning: (text: string, timeout?: number) => |
||||
|
notify({ group: "alert", type: "warning", title: "Warning", text }, timeout || TIMEOUTS.LONG), |
||||
|
|
||||
|
// Info notifications
|
||||
|
info: (text: string, timeout?: number) => |
||||
|
notify({ group: "alert", type: "info", title: "Info", text }, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
// Toast notifications (brief)
|
||||
|
toast: (title: string, text?: string, timeout?: number) => |
||||
|
notify({ group: "alert", type: "toast", title, text }, timeout || TIMEOUTS.BRIEF), |
||||
|
|
||||
|
// Clipboard copy notifications
|
||||
|
copied: (item: string, timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "toast", |
||||
|
title: "Copied", |
||||
|
text: `${item} was copied to the clipboard.` |
||||
|
}, timeout || TIMEOUTS.SHORT), |
||||
|
|
||||
|
// Sent brief notification
|
||||
|
sent: (timeout?: number) => |
||||
|
notify({ group: "alert", type: "toast", title: "Sent..." }, timeout || TIMEOUTS.BRIEF), |
||||
|
|
||||
|
// Confirmation modal
|
||||
|
confirm: (text: string, onYes: () => Promise<void>, timeout?: number) => |
||||
|
notify({ |
||||
|
group: "modal", |
||||
|
type: "confirm", |
||||
|
title: "Confirm", |
||||
|
text, |
||||
|
onYes |
||||
|
}, timeout || TIMEOUTS.MODAL), |
||||
|
|
||||
|
// Standard confirmation messages
|
||||
|
confirmationSubmitted: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: "Success", |
||||
|
text: "Confirmation submitted." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
// Common error patterns
|
||||
|
genericError: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "danger", |
||||
|
title: "Error", |
||||
|
text: "Something went wrong." |
||||
|
}, timeout || TIMEOUTS.LONG), |
||||
|
|
||||
|
// Common success patterns
|
||||
|
genericSuccess: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "success", |
||||
|
title: "Success", |
||||
|
text: "Operation completed successfully." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
// Common confirmation patterns
|
||||
|
alreadyConfirmed: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: "Already Confirmed", |
||||
|
text: "You already confirmed this claim." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
cannotConfirmIssuer: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: "Cannot Confirm", |
||||
|
text: "You cannot confirm this because you issued this claim." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
cannotConfirmHidden: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: "Cannot Confirm", |
||||
|
text: "You cannot confirm this because some people are hidden." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
notRegistered: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: "Not Registered", |
||||
|
text: "Someone needs to register you before you can confirm." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
|
||||
|
notAGive: (timeout?: number) => |
||||
|
notify({ |
||||
|
group: "alert", |
||||
|
type: "info", |
||||
|
title: "Info", |
||||
|
text: "This is not a giving action to confirm." |
||||
|
}, timeout || TIMEOUTS.STANDARD), |
||||
|
}; |
||||
|
} |
Loading…
Reference in new issue