feat: Add notification services for Email, Telegram, and WhatsApp
- Implement EmailNotifier for sending batch and test notifications via email. - Implement TelegramNotifier for sending batch and test notifications via Telegram. - Implement WahaNotifier for sending batch and test notifications via WhatsApp using WAHA API. - Create migration for client_categories table and update clients table to include category_id. - Create migration for notification_settings table to manage notification configurations. - Add ClientCategorySeeder to populate default client categories. - Create manifest.json for PWA support. - Implement service worker (sw.js) for caching static assets and offline support. - Add edit event view for modifying scheduled events. - Create search results view for displaying search queries. - Develop notification settings view for configuring notification channels and triggers.
This commit is contained in:
@@ -6,39 +6,26 @@ Alpine.plugin(sort);
|
||||
window.Alpine = Alpine;
|
||||
Alpine.start();
|
||||
|
||||
// Meow sound toggle (stored in localStorage)
|
||||
// ── PWA Service Worker ────────────────────────────────────────
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js').catch(() => {/* silently fail */});
|
||||
});
|
||||
}
|
||||
|
||||
// ── KolManager helpers (toast notifications only — no meow) ──
|
||||
window.KolManager = {
|
||||
meowEnabled: localStorage.getItem('meow') !== 'false',
|
||||
|
||||
toggleMeow() {
|
||||
this.meowEnabled = !this.meowEnabled;
|
||||
localStorage.setItem('meow', this.meowEnabled);
|
||||
},
|
||||
|
||||
playMeow() {
|
||||
if (!this.meowEnabled) return;
|
||||
const ctx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
const o = ctx.createOscillator();
|
||||
const g = ctx.createGain();
|
||||
o.connect(g);
|
||||
g.connect(ctx.destination);
|
||||
o.type = 'sine';
|
||||
o.frequency.setValueAtTime(880, ctx.currentTime);
|
||||
o.frequency.exponentialRampToValueAtTime(1200, ctx.currentTime + 0.05);
|
||||
o.frequency.exponentialRampToValueAtTime(900, ctx.currentTime + 0.15);
|
||||
g.gain.setValueAtTime(0.3, ctx.currentTime);
|
||||
g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.3);
|
||||
o.start(ctx.currentTime);
|
||||
o.stop(ctx.currentTime + 0.3);
|
||||
},
|
||||
|
||||
notify(msg) {
|
||||
this.playMeow();
|
||||
const el = document.createElement('div');
|
||||
el.className = 'fixed top-4 right-4 z-50 cat-card px-5 py-3 flex items-center gap-2 shadow-lg border border-pink-200 animate-bounce';
|
||||
el.className = 'fixed top-4 right-4 z-50 cat-card px-5 py-3 flex items-center gap-2 shadow-lg border border-pink-200';
|
||||
el.style.cssText = 'animation: slideIn .3s ease';
|
||||
el.innerHTML = `<span class="text-xl">🐱</span><span class="text-sm font-medium text-pink-700">${msg}</span>`;
|
||||
document.body.appendChild(el);
|
||||
setTimeout(() => el.remove(), 3500);
|
||||
setTimeout(() => {
|
||||
el.style.opacity = '0';
|
||||
el.style.transition = 'opacity .3s';
|
||||
setTimeout(() => el.remove(), 300);
|
||||
}, 3200);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -46,7 +33,6 @@ window.KolManager = {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const flash = document.getElementById('flash-message');
|
||||
if (flash) {
|
||||
window.KolManager.playMeow();
|
||||
setTimeout(() => {
|
||||
flash.style.opacity = '0';
|
||||
flash.style.transform = 'translateY(-10px)';
|
||||
|
||||
Reference in New Issue
Block a user