Add notification utility helpers and update PlatformServiceMixin

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.
This commit is contained in:
Matthew Raymer
2025-07-05 11:37:20 +00:00
parent ddee99cb0b
commit b2a2387f1a
6 changed files with 683 additions and 188 deletions

View File

@@ -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);
},
},
};