191 lines
7.4 KiB
JavaScript
191 lines
7.4 KiB
JavaScript
|
export default class LivewireNotification {
|
||
|
constructor(config = {}) {
|
||
|
const defaultConfig = {
|
||
|
notificationTimeout: 6000, // Tiempo predeterminado para las notificaciones
|
||
|
onNotificationShown: null, // Callback al mostrar una notificación
|
||
|
onNotificationRemoved: null, // Callback al eliminar una notificación
|
||
|
onNotificationClosed: null // Callback al cerrar una notificación mediante botón
|
||
|
};
|
||
|
|
||
|
this.config = { ...defaultConfig, ...config };
|
||
|
this.initLivewireNotification();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inicializa la escucha de notificaciones desde Livewire.
|
||
|
*/
|
||
|
initLivewireNotification() {
|
||
|
// Mostrar notificación almacenada después de la recarga
|
||
|
const storedNotification = localStorage.getItem('pendingNotification');
|
||
|
|
||
|
if (storedNotification) {
|
||
|
const event = JSON.parse(storedNotification);
|
||
|
this.showStoredNotification(event);
|
||
|
localStorage.removeItem('pendingNotification'); // Limpiar después de mostrar
|
||
|
}
|
||
|
|
||
|
// Escuchar nuevas notificaciones desde Livewire
|
||
|
Livewire.on('notification', event => {
|
||
|
if (event.deferReload) {
|
||
|
// Guardar la notificación en localStorage para mostrar después de la recarga
|
||
|
localStorage.setItem('pendingNotification', JSON.stringify(event));
|
||
|
|
||
|
window.location.reload();
|
||
|
} else {
|
||
|
// Mostrar la notificación inmediatamente
|
||
|
this.showNotification(event);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Método para emitir notificaciones desde JavaScript.
|
||
|
* @param {Object} options - Opciones de la notificación.
|
||
|
* @param {Function} callback - Callback opcional que se ejecutará después de mostrar la notificación.
|
||
|
* @param {number} customTimeout - Timeout personalizado (opcional).
|
||
|
*/
|
||
|
emitNotification(options, callback, customTimeout) {
|
||
|
const event = {
|
||
|
target: options.target || 'body',
|
||
|
message: options.message || 'Notificación',
|
||
|
type: options.type || 'info',
|
||
|
deferReload: options.deferReload || false,
|
||
|
notificationTimeout: customTimeout || options.notificationTimeout || this.config.notificationTimeout // Usar el timeout personalizado o el predeterminado
|
||
|
};
|
||
|
|
||
|
// Mostrar la notificación
|
||
|
this.showNotification(event);
|
||
|
|
||
|
// Ejecutar callback si está definido
|
||
|
if (typeof callback === 'function') {
|
||
|
callback(event);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Muestra una notificación almacenada.
|
||
|
* @param {Object} event - Datos del evento de notificación.
|
||
|
*/
|
||
|
showStoredNotification(event) {
|
||
|
this.showNotification(event);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Muestra una notificación.
|
||
|
* @param {Object} event - Datos del evento de notificación.
|
||
|
*/
|
||
|
showNotification(event) {
|
||
|
const targetElement = document.querySelector(event.target);
|
||
|
|
||
|
if (!targetElement) {
|
||
|
console.error(`Target ${event.target} no encontrado. Mostrando en el contenedor global.`);
|
||
|
|
||
|
this.showInGlobalContainer(event);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Crear un contenedor para notificaciones si no existe
|
||
|
if (!targetElement.querySelector('.notification-container')) {
|
||
|
const container = document.createElement('div');
|
||
|
|
||
|
container.className = 'notification-container';
|
||
|
targetElement.appendChild(container);
|
||
|
}
|
||
|
|
||
|
const notificationContainer = targetElement.querySelector('.notification-container');
|
||
|
const notificationElement = this.renderNotification(notificationContainer, event);
|
||
|
|
||
|
// Callback opcional al mostrar la notificación
|
||
|
if (typeof this.config.onNotificationShown === 'function') {
|
||
|
this.config.onNotificationShown(notificationElement, event);
|
||
|
}
|
||
|
|
||
|
// Configurar el timeout para eliminar la notificación
|
||
|
this.setNotificationTimeout(notificationElement, event);
|
||
|
|
||
|
// Configurar el evento para el botón de cierre
|
||
|
this.setupCloseButton(notificationElement, event);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Renderiza una notificación en el contenedor global (body).
|
||
|
* @param {Object} event - Datos del evento de notificación.
|
||
|
*/
|
||
|
showInGlobalContainer(event) {
|
||
|
const globalContainer = document.body;
|
||
|
if (!globalContainer.querySelector('.notification-container')) {
|
||
|
const container = document.createElement('div');
|
||
|
|
||
|
container.className = 'notification-container';
|
||
|
globalContainer.appendChild(container);
|
||
|
}
|
||
|
|
||
|
const notificationContainer = globalContainer.querySelector('.notification-container');
|
||
|
const notificationElement = this.renderNotification(notificationContainer, event);
|
||
|
|
||
|
if (typeof this.config.onNotificationShown === 'function') {
|
||
|
this.config.onNotificationShown(notificationElement, event);
|
||
|
}
|
||
|
|
||
|
this.setNotificationTimeout(notificationElement, event);
|
||
|
this.setupCloseButton(notificationElement, event);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Renderiza una notificación en el contenedor.
|
||
|
* @param {HTMLElement} container - Contenedor de notificaciones.
|
||
|
* @param {Object} event - Evento de notificación con tipo y mensaje.
|
||
|
* @returns {HTMLElement} - Elemento de la notificación recién creada.
|
||
|
*/
|
||
|
renderNotification(container, event) {
|
||
|
const notificationElement = document.createElement('div');
|
||
|
|
||
|
notificationElement.className = `alert alert-${event.type} alert-dismissible fade show`;
|
||
|
notificationElement.role = 'alert';
|
||
|
notificationElement.innerHTML = `${event.message} <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>`;
|
||
|
|
||
|
container.appendChild(notificationElement);
|
||
|
|
||
|
return notificationElement;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Configura un timeout para limpiar una notificación específica.
|
||
|
* @param {HTMLElement} notificationElement - Elemento de la notificación.
|
||
|
* @param {Object} event - Evento asociado a la notificación.
|
||
|
*/
|
||
|
setNotificationTimeout(notificationElement, event) {
|
||
|
const timeout = event.notificationTimeout || this.config.notificationTimeout;
|
||
|
|
||
|
setTimeout(() => {
|
||
|
if (notificationElement && notificationElement.parentElement) {
|
||
|
notificationElement.remove();
|
||
|
|
||
|
// Callback opcional al eliminar la notificación
|
||
|
if (typeof this.config.onNotificationRemoved === 'function') {
|
||
|
this.config.onNotificationRemoved(notificationElement, event);
|
||
|
}
|
||
|
}
|
||
|
}, timeout);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Configura el cierre manual de una notificación mediante el botón "Cerrar".
|
||
|
* @param {HTMLElement} notificationElement - Elemento de la notificación.
|
||
|
* @param {Object} event - Evento asociado a la notificación.
|
||
|
*/
|
||
|
setupCloseButton(notificationElement, event) {
|
||
|
const closeButton = notificationElement.querySelector('.btn-close');
|
||
|
if (closeButton) {
|
||
|
closeButton.addEventListener('click', () => {
|
||
|
notificationElement.remove();
|
||
|
|
||
|
// Callback opcional al cerrar la notificación manualmente
|
||
|
if (typeof this.config.onNotificationClosed === 'function') {
|
||
|
this.config.onNotificationClosed(notificationElement, event);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|