custom_ui/frontend/src/stores/notifications-primevue.js

186 lines
4.2 KiB
JavaScript

import { defineStore } from "pinia";
// Global toast instance - will be set during app initialization
let toastInstance = null;
export const useNotificationStore = defineStore("notifications", {
state: () => ({
// Configuration for PrimeVue Toast
defaultLife: 4000,
position: "top-right",
}),
getters: {
// Helper to check if toast is available
isToastAvailable: () => !!toastInstance,
},
actions: {
// Set the toast instance (called from main component)
setToastInstance(toast) {
toastInstance = toast;
},
// Core method to show notifications using PrimeVue Toast
addNotification(notification) {
if (!toastInstance) {
console.warn(
"Toast instance not available. Make sure to call setToastInstance first.",
);
return;
}
const toastMessage = {
severity: this.mapTypesToSeverity(notification.type || "info"),
summary: notification.title || this.getDefaultTitle(notification.type || "info"),
detail: notification.message || "",
life: notification.persistent ? 0 : (notification.duration ?? this.defaultLife),
group: notification.group || "main",
};
toastInstance.add(toastMessage);
},
// Convenience methods for different types of notifications
addSuccess(message, title = "Success", options = {}) {
this.addNotification({
type: "success",
title,
message,
...options,
});
},
addError(message, title = "Error", options = {}) {
this.addNotification({
type: "error",
title,
message,
duration: options.duration ?? 6000, // Errors stay longer by default
...options,
});
},
addWarning(message, title = "Warning", options = {}) {
this.addNotification({
type: "warn",
title,
message,
...options,
});
},
addInfo(message, title = "Info", options = {}) {
this.addNotification({
type: "info",
title,
message,
...options,
});
},
// Show API operation notifications
showApiSuccess(operation, message = null) {
const defaultMessages = {
create: "Item created successfully",
update: "Item updated successfully",
delete: "Item deleted successfully",
fetch: "Data loaded successfully",
};
this.addSuccess(
message || defaultMessages[operation] || "Operation completed successfully",
);
},
showApiError(operation, error, message = null) {
const defaultMessages = {
create: "Failed to create item",
update: "Failed to update item",
delete: "Failed to delete item",
fetch: "Failed to load data",
};
let errorMessage = message;
if (!errorMessage) {
if (typeof error === "string") {
errorMessage = error;
} else if (error?.response?.data?.message) {
errorMessage = error.response.data.message;
} else if (error?.message) {
errorMessage = error.message;
} else {
errorMessage = defaultMessages[operation] || "Operation failed";
}
}
this.addError(errorMessage);
},
// Configuration methods
setPosition(position) {
this.position = position;
},
setDefaultLife(life) {
this.defaultLife = life;
},
// Clear all notifications
clearAll() {
if (toastInstance) {
toastInstance.removeAllGroups();
}
},
// Utility method for handling async operations with notifications
async withNotifications(operation, asyncFunction, options = {}) {
const {
loadingMessage = "Processing...",
successMessage = null,
errorMessage = null,
showLoading = true,
} = options;
try {
if (showLoading) {
this.addInfo(loadingMessage, "Loading", { persistent: true });
}
const result = await asyncFunction();
if (successMessage !== false) {
this.showApiSuccess(operation, successMessage);
}
return result;
} catch (error) {
this.showApiError(operation, error, errorMessage);
throw error;
}
},
// Helper methods
mapTypesToSeverity(type) {
const mapping = {
success: "success",
error: "error",
warn: "warn",
warning: "warn",
info: "info",
};
return mapping[type] || "info";
},
getDefaultTitle(type) {
const titles = {
success: "Success",
error: "Error",
warn: "Warning",
warning: "Warning",
info: "Information",
};
return titles[type] || "Notification";
},
},
});