@ozdao/martyrs 0.2.431 → 0.2.433
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chats.server.js +19 -0
- package/dist/chats.server.mjs +19 -0
- package/dist/martyrs/src/components/Button/{Button.vue2.cjs → Button.vue.cjs} +2 -2
- package/dist/martyrs/src/components/Button/{Button.vue2.js.map → Button.vue.cjs.map} +1 -1
- package/dist/martyrs/src/components/Button/{Button.vue2.js → Button.vue.js} +2 -2
- package/dist/martyrs/src/components/Button/Button.vue.js.map +1 -0
- package/dist/martyrs/src/components/Dropdown/{Dropdown.vue.cjs → Dropdown.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Dropdown/Dropdown.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Dropdown/{Dropdown.vue.js → Dropdown.vue2.js} +2 -2
- package/dist/martyrs/src/components/Dropdown/{Dropdown.vue.cjs.map → Dropdown.vue2.js.map} +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
- package/dist/martyrs/src/components/Menu/{Menu.vue.cjs → Menu.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
- package/dist/martyrs/src/components/SelectMulti/{SelectMulti.vue.cjs → SelectMulti.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/SelectMulti/{SelectMulti.vue.js → SelectMulti.vue2.js} +2 -2
- package/dist/martyrs/src/components/SelectMulti/{SelectMulti.vue.cjs.map → SelectMulti.vue2.js.map} +1 -1
- package/dist/martyrs/src/components/Tab/{Tab.vue2.cjs → Tab.vue.cjs} +2 -2
- package/dist/martyrs/src/components/Tab/{Tab.vue2.js.map → Tab.vue.cjs.map} +1 -1
- package/dist/martyrs/src/components/Tab/{Tab.vue2.js → Tab.vue.js} +2 -2
- package/dist/martyrs/src/components/Tab/Tab.vue.js.map +1 -0
- package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +3 -3
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +3 -3
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +1 -1
- package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.cjs +1 -1
- package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.cjs +1 -1
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +1 -1
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/sections/HotPosts.vue.cjs +1 -1
- package/dist/martyrs/src/modules/community/components/sections/HotPosts.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.cjs +2 -2
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +2 -2
- package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/sections/EventsHot.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/sections/EventsHot.vue.js +1 -1
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.cjs +2 -2
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +2 -2
- package/dist/martyrs/src/modules/globals/views/components/blocks/CardHeader.vue.cjs +2 -2
- package/dist/martyrs/src/modules/globals/views/components/blocks/CardHeader.vue.js +2 -2
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Header.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Header.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/NavigationBar.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/NavigationBar.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.js +1 -1
- package/dist/martyrs/src/modules/landing/landing.client.cjs +0 -6
- package/dist/martyrs/src/modules/landing/landing.client.cjs.map +1 -1
- package/dist/martyrs/src/modules/landing/landing.client.js +0 -6
- package/dist/martyrs/src/modules/landing/landing.client.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/layouts/NotificationsLayout.vue.cjs +1 -1
- package/dist/martyrs/src/modules/notifications/components/layouts/NotificationsLayout.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/layouts/NotificationsLayout.vue.js +1 -1
- package/dist/martyrs/src/modules/notifications/components/layouts/NotificationsLayout.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.cjs +248 -135
- package/dist/martyrs/src/modules/notifications/notifications.client.cjs.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.js +248 -135
- package/dist/martyrs/src/modules/notifications/notifications.client.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +3 -3
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +3 -3
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +3 -3
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +3 -3
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/DetailsTabSection.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/DetailsTabSection.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +2 -2
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.cjs +1 -1
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.cjs +1 -1
- package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardPosition.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardPosition.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/EditLeftover.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/EditLeftover.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditProductInfo.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditProductInfo.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.cjs +2 -2
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +2 -2
- package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.cjs +1 -1
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +2 -2
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +2 -2
- package/dist/style.css +4 -92
- package/package.json +1 -1
- package/src/modules/chats/routes/chats.routes.js +19 -19
- package/src/modules/landing/landing.client.js +6 -6
- package/src/modules/notifications/components/layouts/NotificationsLayout.vue +2 -0
- package/src/modules/notifications/notifications.client.js +351 -167
- package/src/modules/notifications/notifications2.client.js +256 -0
- package/dist/martyrs/src/components/Button/Button.vue2.cjs.map +0 -1
- package/dist/martyrs/src/components/Dropdown/Dropdown.vue.js.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.cjs.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
- package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue.js.map +0 -1
- package/dist/martyrs/src/components/Tab/Tab.vue2.cjs.map +0 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionFeaturesImages.vue.cjs +0 -101
- package/dist/martyrs/src/modules/landing/components/sections/SectionFeaturesImages.vue.cjs.map +0 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionFeaturesImages.vue.js +0 -101
- package/dist/martyrs/src/modules/landing/components/sections/SectionFeaturesImages.vue.js.map +0 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionHeroToken.vue.cjs +0 -85
- package/dist/martyrs/src/modules/landing/components/sections/SectionHeroToken.vue.cjs.map +0 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionHeroToken.vue.js +0 -85
- package/dist/martyrs/src/modules/landing/components/sections/SectionHeroToken.vue.js.map +0 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionRoadmap.vue.cjs +0 -97
- package/dist/martyrs/src/modules/landing/components/sections/SectionRoadmap.vue.cjs.map +0 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionRoadmap.vue.js +0 -97
- package/dist/martyrs/src/modules/landing/components/sections/SectionRoadmap.vue.js.map +0 -1
|
@@ -1,168 +1,322 @@
|
|
|
1
1
|
import { watch, toRefs } from "vue";
|
|
2
|
-
|
|
3
|
-
import
|
|
2
|
+
// Router import
|
|
3
|
+
import routerNotifications from './router/notifications.router.js';
|
|
4
|
+
// Store
|
|
5
|
+
import * as storeNotifications from './store/notifications.store.js';
|
|
6
|
+
// Auth store import
|
|
4
7
|
import * as auth from '@martyrs/src/modules/auth/views/store/auth';
|
|
8
|
+
// Global WebSocket import
|
|
5
9
|
import globalWebSocket from '@martyrs/src/modules/globals/views/classes/globals.websocket.js';
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
10
|
+
// Layouts
|
|
11
|
+
import NotificationsLayout from './components/layouts/NotificationsLayout.vue';
|
|
12
|
+
// Sections
|
|
13
|
+
import NotificationsList from './components/sections/NotificationsList.vue';
|
|
14
|
+
import NotificationPreferences from './components/sections/NotificationPreferences.vue';
|
|
15
|
+
// Pages
|
|
16
|
+
import Notifications from './components/pages/Notifications.vue';
|
|
17
|
+
// Components
|
|
18
|
+
import NotificationBadge from './components/elements/NotificationBadge.vue';
|
|
19
|
+
import NotificationItem from './components/blocks/NotificationItem.vue';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* WebSocket notification handler that uses the global WebSocket connection
|
|
23
|
+
*/
|
|
24
|
+
class WebSocketNotificationHandler {
|
|
25
|
+
constructor(store, options = {}) {
|
|
26
|
+
this.store = store;
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.moduleName = 'notifications';
|
|
29
|
+
this.listeners = [];
|
|
30
|
+
}
|
|
12
31
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Connect to notifications channel
|
|
34
|
+
*/
|
|
35
|
+
connect(userId) {
|
|
36
|
+
// Skip if running in SSR
|
|
37
|
+
if (typeof window === 'undefined' || !userId) {
|
|
38
|
+
return Promise.resolve(false);
|
|
39
|
+
}
|
|
21
40
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
41
|
+
// First ensure the global WebSocket is connected
|
|
42
|
+
return globalWebSocket.connect(userId).then(() => {
|
|
43
|
+
// Register event listeners
|
|
44
|
+
this._registerListeners();
|
|
45
|
+
return true;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
25
48
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
title: notification.title,
|
|
33
|
-
body: notification.body,
|
|
34
|
-
type: notification.type || 'info',
|
|
35
|
-
metadata: notification.metadata || {},
|
|
36
|
-
status: 'unread',
|
|
37
|
-
createdAt: notification.createdAt || new Date().toISOString(),
|
|
38
|
-
updatedAt: notification.updatedAt || new Date().toISOString()
|
|
39
|
-
});
|
|
40
|
-
});
|
|
49
|
+
/**
|
|
50
|
+
* Disconnect notification listeners
|
|
51
|
+
*/
|
|
52
|
+
disconnect() {
|
|
53
|
+
globalWebSocket.removeModuleListeners(this.moduleName);
|
|
54
|
+
}
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Register notification event listeners
|
|
58
|
+
*/
|
|
59
|
+
_registerListeners() {
|
|
60
|
+
// Listen for notification events
|
|
61
|
+
this.listeners.push(
|
|
62
|
+
globalWebSocket.addEventListener('notification', this._processNotification.bind(this), {
|
|
63
|
+
module: this.moduleName
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Listen for notification read status changes
|
|
68
|
+
this.listeners.push(
|
|
69
|
+
globalWebSocket.addEventListener('notification_read', (data) => {
|
|
70
|
+
this.store.notifications.actions.syncNotificationStatus(data.notificationId, 'read');
|
|
71
|
+
}, { module: this.moduleName })
|
|
72
|
+
);
|
|
73
|
+
}
|
|
45
74
|
|
|
46
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Process incoming notification
|
|
77
|
+
*/
|
|
78
|
+
_processNotification(data) {
|
|
79
|
+
if (!data || !data.data) return;
|
|
80
|
+
|
|
81
|
+
const notification = data.data;
|
|
82
|
+
|
|
83
|
+
// Add notification to store
|
|
84
|
+
this.store.notifications.actions.addLocalNotification({
|
|
85
|
+
_id: notification._id,
|
|
86
|
+
title: notification.title,
|
|
87
|
+
body: notification.body,
|
|
88
|
+
type: notification.type || 'info',
|
|
89
|
+
metadata: notification.metadata || {},
|
|
90
|
+
status: 'unread',
|
|
91
|
+
createdAt: notification.createdAt || new Date().toISOString(),
|
|
92
|
+
updatedAt: notification.updatedAt || new Date().toISOString()
|
|
47
93
|
});
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
disconnect: (moduleName, listeners) => {
|
|
51
|
-
if (listeners) {
|
|
52
|
-
globalWebSocket.removeModuleListeners(moduleName);
|
|
53
|
-
}
|
|
54
94
|
}
|
|
55
|
-
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Capacitor Push Notification handler
|
|
99
|
+
*/
|
|
100
|
+
class CapacitorPushHandler {
|
|
101
|
+
constructor(store) {
|
|
102
|
+
this.store = store;
|
|
103
|
+
this.pushNotifications = null;
|
|
104
|
+
this.device = null;
|
|
105
|
+
this.isInitialized = false;
|
|
106
|
+
}
|
|
56
107
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Initialize Capacitor plugins
|
|
110
|
+
*/
|
|
111
|
+
async initialize() {
|
|
112
|
+
// Skip if running in SSR
|
|
113
|
+
if (typeof window === 'undefined') {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
61
116
|
|
|
62
117
|
try {
|
|
118
|
+
// Dynamic imports to prevent errors in web environment
|
|
63
119
|
const { Capacitor } = await import('@capacitor/core');
|
|
64
120
|
const { PushNotifications } = await import('@capacitor/push-notifications');
|
|
65
121
|
const { Device } = await import('@capacitor/device');
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
122
|
+
|
|
123
|
+
this.capacitor = Capacitor;
|
|
124
|
+
this.pushNotifications = PushNotifications;
|
|
125
|
+
this.device = Device;
|
|
126
|
+
|
|
127
|
+
// Only proceed if running on a native platform
|
|
128
|
+
if (!this.capacitor.isNativePlatform()) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.isInitialized = true;
|
|
133
|
+
return true;
|
|
70
134
|
} catch (error) {
|
|
71
135
|
console.error('Error importing Capacitor plugins:', error);
|
|
72
136
|
return false;
|
|
73
137
|
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
requestPermissions: async (store) => {
|
|
77
|
-
if (typeof window === 'undefined') return false;
|
|
78
|
-
|
|
79
|
-
const plugins = await pushNotificationHandlers.initialize();
|
|
80
|
-
if (!plugins) return false;
|
|
81
|
-
|
|
82
|
-
const { pushNotifications, device } = plugins;
|
|
138
|
+
}
|
|
83
139
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Request permission and register for push notifications
|
|
142
|
+
*/
|
|
143
|
+
async requestPermissions() {
|
|
144
|
+
// Skip if running in SSR
|
|
145
|
+
if (typeof window === 'undefined') {
|
|
87
146
|
return false;
|
|
88
147
|
}
|
|
89
148
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const deviceId = await device.getId();
|
|
95
|
-
|
|
96
|
-
const deviceData = {
|
|
97
|
-
deviceId: deviceId.uuid,
|
|
98
|
-
deviceType: deviceInfo.platform.toLowerCase(),
|
|
99
|
-
deviceToken: token.value
|
|
100
|
-
};
|
|
149
|
+
if (!this.isInitialized) {
|
|
150
|
+
const initialized = await this.initialize();
|
|
151
|
+
if (!initialized) return false;
|
|
152
|
+
}
|
|
101
153
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
154
|
+
try {
|
|
155
|
+
// Request permission
|
|
156
|
+
const permissionResult = await this.pushNotifications.requestPermissions();
|
|
157
|
+
if (permissionResult.receive !== 'granted') {
|
|
158
|
+
console.log('Push notification permission denied');
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Set up event listeners
|
|
163
|
+
this._setupListeners();
|
|
164
|
+
|
|
165
|
+
// Register with Apple/Google
|
|
166
|
+
await this.pushNotifications.register();
|
|
167
|
+
return true;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error('Error requesting push notification permissions:', error);
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
107
173
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Setup push notification event listeners
|
|
176
|
+
*/
|
|
177
|
+
_setupListeners() {
|
|
178
|
+
// Registration event
|
|
179
|
+
this.pushNotifications.addListener('registration',
|
|
180
|
+
this._handleRegistration.bind(this)
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
// Notification received event
|
|
184
|
+
this.pushNotifications.addListener('pushNotificationReceived',
|
|
185
|
+
this._handleNotificationReceived.bind(this)
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Notification action performed event
|
|
189
|
+
this.pushNotifications.addListener('pushNotificationActionPerformed',
|
|
190
|
+
this._handleNotificationAction.bind(this)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
115
193
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Handle registration token received
|
|
196
|
+
*/
|
|
197
|
+
async _handleRegistration(token) {
|
|
198
|
+
try {
|
|
199
|
+
// Get device info
|
|
200
|
+
const deviceInfo = await this.device.getInfo();
|
|
201
|
+
const deviceId = await this.device.getId();
|
|
202
|
+
|
|
203
|
+
// Prepare device data
|
|
204
|
+
const deviceData = {
|
|
205
|
+
deviceId: deviceId.uuid,
|
|
206
|
+
deviceType: deviceInfo.platform.toLowerCase(),
|
|
207
|
+
deviceToken: token.value
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// Register device with backend
|
|
211
|
+
await this.store.notifications.actions.registerDevice(deviceData);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error('Error handling push registration:', error);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
122
216
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
217
|
+
/**
|
|
218
|
+
* Handle received notification
|
|
219
|
+
*/
|
|
220
|
+
_handleNotificationReceived(notification) {
|
|
221
|
+
// Add notification to store
|
|
222
|
+
this.store.notifications.actions.addLocalNotification({
|
|
223
|
+
title: notification.title,
|
|
224
|
+
body: notification.body,
|
|
225
|
+
data: notification.data || {}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
127
228
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Handle notification action (when user taps on notification)
|
|
231
|
+
*/
|
|
232
|
+
_handleNotificationAction(actionData) {
|
|
233
|
+
if (actionData.notification && actionData.notification.data) {
|
|
234
|
+
this.store.notifications.actions.handleNotificationAction(
|
|
235
|
+
actionData.notification.data
|
|
236
|
+
);
|
|
237
|
+
}
|
|
131
238
|
}
|
|
132
|
-
};
|
|
133
239
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Remove push notification listeners
|
|
242
|
+
*/
|
|
243
|
+
removeListeners() {
|
|
244
|
+
if (typeof window === 'undefined') {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (this.pushNotifications) {
|
|
249
|
+
this.pushNotifications.removeAllListeners();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Notification Manager for coordinating WebSocket and Push notifications
|
|
256
|
+
*/
|
|
257
|
+
class NotificationManager {
|
|
258
|
+
constructor(store, options = {}) {
|
|
259
|
+
this.store = store;
|
|
260
|
+
this.options = options;
|
|
261
|
+
this.wsHandler = new WebSocketNotificationHandler(store, options);
|
|
262
|
+
this.pushHandler = new CapacitorPushHandler(store);
|
|
263
|
+
this.initialized = false;
|
|
264
|
+
this.isServer = typeof window === 'undefined';
|
|
265
|
+
}
|
|
138
266
|
|
|
139
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Initialize notifications
|
|
269
|
+
*/
|
|
270
|
+
async initialize() {
|
|
271
|
+
if (this.initialized || this.isServer) return;
|
|
272
|
+
|
|
273
|
+
// Get current user ID from auth store instead of localStorage
|
|
274
|
+
const userId = this.store.auth.state.user?._id;
|
|
140
275
|
if (!userId) {
|
|
141
276
|
console.warn('Cannot initialize notifications: No user ID found in auth store');
|
|
142
277
|
return;
|
|
143
278
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
279
|
+
|
|
280
|
+
// Initialize WebSocket for realtime notifications
|
|
281
|
+
await this.wsHandler.connect(userId);
|
|
282
|
+
|
|
283
|
+
// Initialize push notifications for mobile if enabled
|
|
284
|
+
if (this.options.enablePush !== false) {
|
|
285
|
+
await this.pushHandler.requestPermissions();
|
|
148
286
|
}
|
|
287
|
+
|
|
288
|
+
this.initialized = true;
|
|
289
|
+
|
|
290
|
+
// Fetch existing notifications
|
|
291
|
+
await this.store.notifications.actions.getNotifications(userId);
|
|
292
|
+
}
|
|
149
293
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
294
|
+
/**
|
|
295
|
+
* Disconnect and clean up
|
|
296
|
+
*/
|
|
297
|
+
disconnect() {
|
|
298
|
+
if (this.isServer) return;
|
|
299
|
+
|
|
300
|
+
this.wsHandler.disconnect();
|
|
301
|
+
this.pushHandler.removeListeners();
|
|
302
|
+
this.initialized = false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Server-side utility for pre-fetching notification data
|
|
308
|
+
*/
|
|
309
|
+
const SSRUtils = {
|
|
310
|
+
/**
|
|
311
|
+
* Pre-fetch notifications for SSR
|
|
312
|
+
* @param {Object} store - Store instance
|
|
313
|
+
* @param {Object} context - SSR context
|
|
314
|
+
*/
|
|
315
|
+
async prefetchNotifications(store, context) {
|
|
163
316
|
try {
|
|
164
317
|
const userId = store.auth.state.user?._id;
|
|
165
318
|
if (userId) {
|
|
319
|
+
// Fetch notifications without WebSocket or push setup
|
|
166
320
|
await store.notifications.actions.getNotifications(userId);
|
|
167
321
|
}
|
|
168
322
|
} catch (error) {
|
|
@@ -171,86 +325,116 @@ const notificationUtils = {
|
|
|
171
325
|
}
|
|
172
326
|
};
|
|
173
327
|
|
|
174
|
-
|
|
175
|
-
|
|
328
|
+
/**
|
|
329
|
+
* Function to initialize the notifications module
|
|
330
|
+
* @param {Object} app - Vue app instance
|
|
331
|
+
* @param {Object} store - Vuex/Pinia store
|
|
332
|
+
* @param {Object} router - Vue Router instance
|
|
333
|
+
* @param {Object} options - Configuration options
|
|
334
|
+
*/
|
|
335
|
+
function initializeNotifications(app, store, router, options = {}) {
|
|
336
|
+
// Add routes and store
|
|
176
337
|
const route = options.route || 'User Profile Root';
|
|
177
338
|
router.addRoute(route, routerNotifications);
|
|
178
339
|
store.addStore('notifications', storeNotifications);
|
|
179
|
-
|
|
340
|
+
|
|
341
|
+
// Initialize global WebSocket if needed
|
|
180
342
|
if (options.wsUrl) {
|
|
181
343
|
globalWebSocket.initialize({ wsUrl: options.wsUrl });
|
|
182
344
|
}
|
|
183
|
-
|
|
345
|
+
|
|
346
|
+
// Create notification manager
|
|
347
|
+
const notificationManager = new NotificationManager(store, {
|
|
348
|
+
enablePush: options.enablePush !== false,
|
|
349
|
+
maxReconnectAttempts: options.maxReconnectAttempts || 5,
|
|
350
|
+
reconnectDelay: options.reconnectDelay || 3000,
|
|
351
|
+
pingInterval: options.pingInterval || 30000
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Attach notification manager to store for access in components
|
|
355
|
+
store.notificationManager = notificationManager;
|
|
356
|
+
|
|
357
|
+
// Don't auto-initialize on server
|
|
184
358
|
const isServer = typeof window === 'undefined';
|
|
185
359
|
const autoInit = !isServer && options.autoInit !== false;
|
|
186
|
-
|
|
187
|
-
let notificationManager = null;
|
|
188
|
-
|
|
360
|
+
|
|
189
361
|
if (autoInit) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
};
|
|
200
|
-
|
|
362
|
+
// Initialize after auth is confirmed
|
|
363
|
+
const isAuthenticated = store.auth.state.isAuthenticated;
|
|
364
|
+
const userId = store.auth.state.user?._id;
|
|
365
|
+
|
|
366
|
+
if (isAuthenticated && userId) {
|
|
367
|
+
notificationManager.initialize();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Watch for user login/logout using auth store
|
|
201
371
|
watch(() => store.auth.state.isAuthenticated, (isAuthenticated) => {
|
|
202
372
|
if (isAuthenticated) {
|
|
203
|
-
|
|
204
|
-
} else
|
|
373
|
+
notificationManager.initialize();
|
|
374
|
+
} else {
|
|
205
375
|
notificationManager.disconnect();
|
|
206
376
|
store.notifications.mutations.resetNotifications();
|
|
207
|
-
notificationManager = null;
|
|
208
377
|
}
|
|
209
378
|
});
|
|
210
|
-
|
|
211
|
-
if (store.auth.state.isAuthenticated) {
|
|
212
|
-
initNotifications();
|
|
213
|
-
}
|
|
214
379
|
}
|
|
380
|
+
|
|
381
|
+
// Provide composable for components to access notification functionality
|
|
382
|
+
app.provide('useNotifications', () => {
|
|
383
|
+
return {
|
|
384
|
+
...toRefs(store.notifications.state),
|
|
385
|
+
...store.notifications.actions,
|
|
386
|
+
...store.notifications.mutations,
|
|
387
|
+
init: notificationManager.initialize.bind(notificationManager),
|
|
388
|
+
disconnect: notificationManager.disconnect.bind(notificationManager),
|
|
389
|
+
isServer
|
|
390
|
+
};
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
return notificationManager;
|
|
394
|
+
}
|
|
215
395
|
|
|
216
|
-
|
|
217
|
-
...toRefs(store.notifications.state),
|
|
218
|
-
...store.notifications.actions,
|
|
219
|
-
...store.notifications.mutations,
|
|
220
|
-
init: () => notificationUtils.initialize(store, options),
|
|
221
|
-
disconnect: () => notificationManager?.disconnect(),
|
|
222
|
-
isServer
|
|
223
|
-
}));
|
|
224
|
-
|
|
225
|
-
return {
|
|
226
|
-
SSR: { prefetchNotifications: notificationUtils.prefetchForSSR }
|
|
227
|
-
};
|
|
228
|
-
};
|
|
229
|
-
|
|
396
|
+
// Module export
|
|
230
397
|
const ModuleNotifications = {
|
|
231
398
|
initialize: initializeNotifications,
|
|
399
|
+
SSR: SSRUtils, // Export SSR utilities
|
|
232
400
|
views: {
|
|
233
|
-
store: {
|
|
234
|
-
|
|
401
|
+
store: {
|
|
402
|
+
storeNotifications,
|
|
403
|
+
},
|
|
404
|
+
router: {
|
|
405
|
+
routerNotifications
|
|
406
|
+
},
|
|
235
407
|
components: {
|
|
408
|
+
// Elements
|
|
236
409
|
NotificationBadge,
|
|
410
|
+
// Blocks
|
|
237
411
|
NotificationItem,
|
|
412
|
+
// Sections
|
|
238
413
|
NotificationsList,
|
|
239
414
|
NotificationPreferences,
|
|
415
|
+
// Pages
|
|
240
416
|
Notifications,
|
|
417
|
+
// Layouts
|
|
241
418
|
NotificationsLayout
|
|
242
419
|
}
|
|
243
420
|
}
|
|
244
421
|
};
|
|
245
422
|
|
|
423
|
+
// Component exports
|
|
246
424
|
export {
|
|
425
|
+
// Elements
|
|
247
426
|
NotificationBadge,
|
|
427
|
+
// Blocks
|
|
248
428
|
NotificationItem,
|
|
429
|
+
// Sections
|
|
249
430
|
NotificationsList,
|
|
250
431
|
NotificationPreferences,
|
|
432
|
+
// Pages
|
|
251
433
|
Notifications,
|
|
434
|
+
// Layouts
|
|
252
435
|
NotificationsLayout,
|
|
253
|
-
|
|
436
|
+
// SSR Utilities
|
|
437
|
+
SSRUtils
|
|
254
438
|
};
|
|
255
439
|
|
|
256
|
-
export default ModuleNotifications;
|
|
440
|
+
export default ModuleNotifications;
|