shared-features 0.0.3 → 0.0.5
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/README.md +2 -0
- package/dist/{AdBanner-D-KuNTje.cjs → AnnouncementModal-Bqy0pn3V.cjs} +432 -4
- package/dist/AnnouncementModal-Bqy0pn3V.cjs.map +1 -0
- package/dist/{AdBanner-Ben0vVXV.js → AnnouncementModal-sxH4K5gy.js} +434 -6
- package/dist/AnnouncementModal-sxH4K5gy.js.map +1 -0
- package/dist/admin-notifications-D9n9h-eY.cjs +362 -0
- package/dist/admin-notifications-D9n9h-eY.cjs.map +1 -0
- package/dist/admin-notifications-p1dy3zIP.js +363 -0
- package/dist/admin-notifications-p1dy3zIP.js.map +1 -0
- package/dist/{analytics-CdpCtTpu.js → analytics-40-S_fHC.js} +3 -2
- package/dist/{analytics-CdpCtTpu.js.map → analytics-40-S_fHC.js.map} +1 -1
- package/dist/{analytics--ZSO9ova.cjs → analytics-lEzOx2vl.cjs} +2 -1
- package/dist/{analytics--ZSO9ova.cjs.map → analytics-lEzOx2vl.cjs.map} +1 -1
- package/dist/broadcasts-3_WfQMNL.cjs +278 -0
- package/dist/broadcasts-3_WfQMNL.cjs.map +1 -0
- package/dist/broadcasts-DgZUzqMf.js +257 -0
- package/dist/broadcasts-DgZUzqMf.js.map +1 -0
- package/dist/components/ads/AdModal.d.ts.map +1 -1
- package/dist/components/index.cjs +23 -20
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -1
- package/dist/components/notifications/AnnouncementModal.d.ts +21 -0
- package/dist/components/notifications/AnnouncementModal.d.ts.map +1 -0
- package/dist/components/notifications/BroadcastBanner.d.ts +55 -0
- package/dist/components/notifications/BroadcastBanner.d.ts.map +1 -0
- package/dist/components/notifications/index.d.ts +11 -0
- package/dist/components/notifications/index.d.ts.map +1 -0
- package/dist/hooks/index.cjs +9 -1
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +9 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useBroadcasts.d.ts +122 -0
- package/dist/hooks/useBroadcasts.d.ts.map +1 -0
- package/dist/index.cjs +99 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +94 -17
- package/dist/index.js.map +1 -1
- package/dist/notifications/events/index.d.ts +14 -0
- package/dist/notifications/events/index.d.ts.map +1 -0
- package/dist/notifications/events/registry.d.ts +75 -0
- package/dist/notifications/events/registry.d.ts.map +1 -0
- package/dist/notifications/events/templates/engine.d.ts +57 -0
- package/dist/notifications/events/templates/engine.d.ts.map +1 -0
- package/dist/notifications/events/templates/standard.d.ts +20 -0
- package/dist/notifications/events/templates/standard.d.ts.map +1 -0
- package/dist/notifications/events/useNotificationEvents.d.ts +36 -0
- package/dist/notifications/events/useNotificationEvents.d.ts.map +1 -0
- package/dist/notifications/index.cjs +25 -0
- package/dist/notifications/index.cjs.map +1 -0
- package/dist/notifications/index.d.ts +9 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +25 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/services/admin-notifications.d.ts +95 -0
- package/dist/services/admin-notifications.d.ts.map +1 -0
- package/dist/services/broadcasts.d.ts +55 -0
- package/dist/services/broadcasts.d.ts.map +1 -0
- package/dist/services/index.cjs +34 -1
- package/dist/services/index.cjs.map +1 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +35 -2
- package/dist/services/index.js.map +1 -1
- package/dist/types/index.cjs +108 -0
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +109 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/notifications.d.ts +634 -0
- package/dist/types/notifications.d.ts.map +1 -0
- package/dist/useBroadcasts-DzpCcbC8.js +161 -0
- package/dist/useBroadcasts-DzpCcbC8.js.map +1 -0
- package/dist/useBroadcasts-FP6ZrcY_.cjs +160 -0
- package/dist/useBroadcasts-FP6ZrcY_.cjs.map +1 -0
- package/dist/{useCampaigns-Dltisb9N.cjs → useCampaigns-BOZ9dDsG.cjs} +2 -2
- package/dist/{useCampaigns-Dltisb9N.cjs.map → useCampaigns-BOZ9dDsG.cjs.map} +1 -1
- package/dist/{useCampaigns-nwfsALsN.js → useCampaigns-D46b9zuf.js} +2 -2
- package/dist/{useCampaigns-nwfsALsN.js.map → useCampaigns-D46b9zuf.js.map} +1 -1
- package/dist/useNotificationEvents-BXeMqdak.cjs +954 -0
- package/dist/useNotificationEvents-BXeMqdak.cjs.map +1 -0
- package/dist/useNotificationEvents-D8DVxah1.js +955 -0
- package/dist/useNotificationEvents-D8DVxah1.js.map +1 -0
- package/package.json +13 -5
- package/dist/AdBanner-Ben0vVXV.js.map +0 -1
- package/dist/AdBanner-D-KuNTje.cjs.map +0 -1
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const firestore = require("firebase/firestore");
|
|
3
|
+
const analytics = require("./analytics-lEzOx2vl.cjs");
|
|
4
|
+
const COLLECTION_BROADCASTS = "zaions_broadcasts";
|
|
5
|
+
const COLLECTION_TEMPLATES = "zaions_notification_templates";
|
|
6
|
+
const COLLECTION_BROADCAST_EVENTS = "zaions_broadcast_events";
|
|
7
|
+
function docToBroadcast(docId, data) {
|
|
8
|
+
return {
|
|
9
|
+
id: docId,
|
|
10
|
+
title: data.title,
|
|
11
|
+
message: data.message,
|
|
12
|
+
type: data.type,
|
|
13
|
+
category: data.category,
|
|
14
|
+
isRead: false,
|
|
15
|
+
isImportant: data.isImportant,
|
|
16
|
+
actionUrl: data.actionUrl,
|
|
17
|
+
actionText: data.actionText,
|
|
18
|
+
createdAt: data.createdAt,
|
|
19
|
+
metadata: data.metadata,
|
|
20
|
+
targetProjects: data.targetProjects || [],
|
|
21
|
+
targetPlatforms: data.targetPlatforms || [],
|
|
22
|
+
targetAudience: data.targetAudience || "all",
|
|
23
|
+
status: data.status,
|
|
24
|
+
startDate: data.startDate,
|
|
25
|
+
endDate: data.endDate,
|
|
26
|
+
priority: data.priority || 50,
|
|
27
|
+
dismissible: data.dismissible !== false,
|
|
28
|
+
variant: data.variant || "banner",
|
|
29
|
+
impressions: data.impressions || 0,
|
|
30
|
+
clicks: data.clicks || 0,
|
|
31
|
+
createdBy: data.createdBy,
|
|
32
|
+
updatedBy: data.updatedBy
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function docToTemplate(docId, data) {
|
|
36
|
+
return {
|
|
37
|
+
id: docId,
|
|
38
|
+
name: data.name,
|
|
39
|
+
eventType: data.eventType,
|
|
40
|
+
category: data.category,
|
|
41
|
+
title: data.title,
|
|
42
|
+
message: data.message,
|
|
43
|
+
variables: data.variables || [],
|
|
44
|
+
type: data.type,
|
|
45
|
+
isImportant: data.isImportant,
|
|
46
|
+
actionUrl: data.actionUrl,
|
|
47
|
+
actionText: data.actionText,
|
|
48
|
+
enabled: data.enabled !== false,
|
|
49
|
+
createdAt: data.createdAt?.toDate() || /* @__PURE__ */ new Date(),
|
|
50
|
+
updatedAt: data.updatedAt?.toDate() || /* @__PURE__ */ new Date()
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async function createBroadcast(input, adminUserId) {
|
|
54
|
+
const db = analytics.getSharedFeaturesDb();
|
|
55
|
+
const broadcastData = {
|
|
56
|
+
...input,
|
|
57
|
+
status: "draft",
|
|
58
|
+
isRead: false,
|
|
59
|
+
impressions: 0,
|
|
60
|
+
clicks: 0,
|
|
61
|
+
createdBy: adminUserId,
|
|
62
|
+
createdAt: firestore.serverTimestamp(),
|
|
63
|
+
startDate: firestore.Timestamp.fromDate(input.startDate),
|
|
64
|
+
endDate: input.endDate ? firestore.Timestamp.fromDate(input.endDate) : null
|
|
65
|
+
};
|
|
66
|
+
const docRef = await firestore.addDoc(
|
|
67
|
+
firestore.collection(db, COLLECTION_BROADCASTS),
|
|
68
|
+
broadcastData
|
|
69
|
+
);
|
|
70
|
+
return docRef.id;
|
|
71
|
+
}
|
|
72
|
+
async function updateBroadcast(input, adminUserId) {
|
|
73
|
+
const db = analytics.getSharedFeaturesDb();
|
|
74
|
+
const updateData = {
|
|
75
|
+
...input,
|
|
76
|
+
updatedBy: adminUserId,
|
|
77
|
+
updatedAt: firestore.serverTimestamp()
|
|
78
|
+
};
|
|
79
|
+
if (input.startDate) {
|
|
80
|
+
updateData.startDate = firestore.Timestamp.fromDate(input.startDate);
|
|
81
|
+
}
|
|
82
|
+
if (input.endDate !== void 0) {
|
|
83
|
+
updateData.endDate = input.endDate ? firestore.Timestamp.fromDate(input.endDate) : null;
|
|
84
|
+
}
|
|
85
|
+
delete updateData.id;
|
|
86
|
+
await firestore.updateDoc(firestore.doc(db, COLLECTION_BROADCASTS, input.id), updateData);
|
|
87
|
+
}
|
|
88
|
+
async function deleteBroadcast(broadcastId) {
|
|
89
|
+
const db = analytics.getSharedFeaturesDb();
|
|
90
|
+
await firestore.deleteDoc(firestore.doc(db, COLLECTION_BROADCASTS, broadcastId));
|
|
91
|
+
}
|
|
92
|
+
async function getAllBroadcasts() {
|
|
93
|
+
const db = analytics.getSharedFeaturesDb();
|
|
94
|
+
const q = firestore.query(
|
|
95
|
+
firestore.collection(db, COLLECTION_BROADCASTS),
|
|
96
|
+
firestore.orderBy("createdAt", "desc")
|
|
97
|
+
);
|
|
98
|
+
const snapshot = await firestore.getDocs(q);
|
|
99
|
+
return snapshot.docs.map((d) => docToBroadcast(d.id, d.data()));
|
|
100
|
+
}
|
|
101
|
+
async function getBroadcastsByStatus(status) {
|
|
102
|
+
const db = analytics.getSharedFeaturesDb();
|
|
103
|
+
const q = firestore.query(
|
|
104
|
+
firestore.collection(db, COLLECTION_BROADCASTS),
|
|
105
|
+
firestore.where("status", "==", status),
|
|
106
|
+
firestore.orderBy("createdAt", "desc")
|
|
107
|
+
);
|
|
108
|
+
const snapshot = await firestore.getDocs(q);
|
|
109
|
+
return snapshot.docs.map((d) => docToBroadcast(d.id, d.data()));
|
|
110
|
+
}
|
|
111
|
+
async function getBroadcastById(broadcastId) {
|
|
112
|
+
const db = analytics.getSharedFeaturesDb();
|
|
113
|
+
const docSnap = await firestore.getDoc(firestore.doc(db, COLLECTION_BROADCASTS, broadcastId));
|
|
114
|
+
if (!docSnap.exists()) return null;
|
|
115
|
+
return docToBroadcast(docSnap.id, docSnap.data());
|
|
116
|
+
}
|
|
117
|
+
async function publishBroadcast(broadcastId, adminUserId) {
|
|
118
|
+
const db = analytics.getSharedFeaturesDb();
|
|
119
|
+
await firestore.updateDoc(firestore.doc(db, COLLECTION_BROADCASTS, broadcastId), {
|
|
120
|
+
status: "active",
|
|
121
|
+
updatedBy: adminUserId,
|
|
122
|
+
updatedAt: firestore.serverTimestamp()
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async function scheduleBroadcast(broadcastId, scheduledDate, adminUserId) {
|
|
126
|
+
const db = analytics.getSharedFeaturesDb();
|
|
127
|
+
await firestore.updateDoc(firestore.doc(db, COLLECTION_BROADCASTS, broadcastId), {
|
|
128
|
+
status: "scheduled",
|
|
129
|
+
startDate: firestore.Timestamp.fromDate(scheduledDate),
|
|
130
|
+
updatedBy: adminUserId,
|
|
131
|
+
updatedAt: firestore.serverTimestamp()
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async function pauseBroadcast(broadcastId, adminUserId) {
|
|
135
|
+
const db = analytics.getSharedFeaturesDb();
|
|
136
|
+
await firestore.updateDoc(firestore.doc(db, COLLECTION_BROADCASTS, broadcastId), {
|
|
137
|
+
status: "draft",
|
|
138
|
+
// Move back to draft
|
|
139
|
+
updatedBy: adminUserId,
|
|
140
|
+
updatedAt: firestore.serverTimestamp()
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async function endBroadcast(broadcastId, adminUserId) {
|
|
144
|
+
const db = analytics.getSharedFeaturesDb();
|
|
145
|
+
await firestore.updateDoc(firestore.doc(db, COLLECTION_BROADCASTS, broadcastId), {
|
|
146
|
+
status: "ended",
|
|
147
|
+
endDate: firestore.serverTimestamp(),
|
|
148
|
+
updatedBy: adminUserId,
|
|
149
|
+
updatedAt: firestore.serverTimestamp()
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
async function createTemplate(input) {
|
|
153
|
+
const db = analytics.getSharedFeaturesDb();
|
|
154
|
+
const templateData = {
|
|
155
|
+
...input,
|
|
156
|
+
createdAt: firestore.serverTimestamp(),
|
|
157
|
+
updatedAt: firestore.serverTimestamp()
|
|
158
|
+
};
|
|
159
|
+
const docRef = await firestore.addDoc(
|
|
160
|
+
firestore.collection(db, COLLECTION_TEMPLATES),
|
|
161
|
+
templateData
|
|
162
|
+
);
|
|
163
|
+
return docRef.id;
|
|
164
|
+
}
|
|
165
|
+
async function updateTemplate(templateId, input) {
|
|
166
|
+
const db = analytics.getSharedFeaturesDb();
|
|
167
|
+
await firestore.updateDoc(firestore.doc(db, COLLECTION_TEMPLATES, templateId), {
|
|
168
|
+
...input,
|
|
169
|
+
updatedAt: firestore.serverTimestamp()
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async function deleteTemplate(templateId) {
|
|
173
|
+
const db = analytics.getSharedFeaturesDb();
|
|
174
|
+
await firestore.deleteDoc(firestore.doc(db, COLLECTION_TEMPLATES, templateId));
|
|
175
|
+
}
|
|
176
|
+
async function getAllTemplates() {
|
|
177
|
+
const db = analytics.getSharedFeaturesDb();
|
|
178
|
+
const q = firestore.query(
|
|
179
|
+
firestore.collection(db, COLLECTION_TEMPLATES),
|
|
180
|
+
firestore.orderBy("name", "asc")
|
|
181
|
+
);
|
|
182
|
+
const snapshot = await firestore.getDocs(q);
|
|
183
|
+
return snapshot.docs.map((d) => docToTemplate(d.id, d.data()));
|
|
184
|
+
}
|
|
185
|
+
async function getTemplateById(templateId) {
|
|
186
|
+
const db = analytics.getSharedFeaturesDb();
|
|
187
|
+
const docSnap = await firestore.getDoc(firestore.doc(db, COLLECTION_TEMPLATES, templateId));
|
|
188
|
+
if (!docSnap.exists()) return null;
|
|
189
|
+
return docToTemplate(docSnap.id, docSnap.data());
|
|
190
|
+
}
|
|
191
|
+
async function getFirestoreTemplateByEventType(eventType) {
|
|
192
|
+
const db = analytics.getSharedFeaturesDb();
|
|
193
|
+
const q = firestore.query(
|
|
194
|
+
firestore.collection(db, COLLECTION_TEMPLATES),
|
|
195
|
+
firestore.where("eventType", "==", eventType)
|
|
196
|
+
);
|
|
197
|
+
const snapshot = await firestore.getDocs(q);
|
|
198
|
+
if (snapshot.empty) return null;
|
|
199
|
+
const docSnap = snapshot.docs[0];
|
|
200
|
+
if (!docSnap) return null;
|
|
201
|
+
return docToTemplate(docSnap.id, docSnap.data());
|
|
202
|
+
}
|
|
203
|
+
async function getBroadcastAnalytics(broadcastId) {
|
|
204
|
+
const db = analytics.getSharedFeaturesDb();
|
|
205
|
+
const broadcast = await getBroadcastById(broadcastId);
|
|
206
|
+
if (!broadcast) return null;
|
|
207
|
+
const eventsQuery = firestore.query(
|
|
208
|
+
firestore.collection(db, COLLECTION_BROADCAST_EVENTS),
|
|
209
|
+
firestore.where("broadcastId", "==", broadcastId)
|
|
210
|
+
);
|
|
211
|
+
const eventsSnapshot = await firestore.getDocs(eventsQuery);
|
|
212
|
+
const events = eventsSnapshot.docs.map((d) => d.data());
|
|
213
|
+
const impressions = events.filter((e) => e.action === "impression").length;
|
|
214
|
+
const clicks = events.filter((e) => e.action === "click").length;
|
|
215
|
+
const dismissals = events.filter((e) => e.action === "dismiss").length;
|
|
216
|
+
const byPlatform = {
|
|
217
|
+
web: { impressions: 0, clicks: 0 },
|
|
218
|
+
android: { impressions: 0, clicks: 0 },
|
|
219
|
+
ios: { impressions: 0, clicks: 0 }
|
|
220
|
+
};
|
|
221
|
+
events.forEach((e) => {
|
|
222
|
+
const platform = e.platform;
|
|
223
|
+
if (byPlatform[platform]) {
|
|
224
|
+
if (e.action === "impression") byPlatform[platform].impressions++;
|
|
225
|
+
if (e.action === "click") byPlatform[platform].clicks++;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
const byProject = {};
|
|
229
|
+
events.forEach((e) => {
|
|
230
|
+
const projectId = e.projectId;
|
|
231
|
+
if (!byProject[projectId]) {
|
|
232
|
+
byProject[projectId] = { impressions: 0, clicks: 0 };
|
|
233
|
+
}
|
|
234
|
+
if (e.action === "impression") byProject[projectId].impressions++;
|
|
235
|
+
if (e.action === "click") byProject[projectId].clicks++;
|
|
236
|
+
});
|
|
237
|
+
const byDateMap = {};
|
|
238
|
+
events.forEach((e) => {
|
|
239
|
+
const dateStr = e.timestamp.toDate().toISOString().split("T")[0];
|
|
240
|
+
if (dateStr) {
|
|
241
|
+
if (!byDateMap[dateStr]) {
|
|
242
|
+
byDateMap[dateStr] = { impressions: 0, clicks: 0 };
|
|
243
|
+
}
|
|
244
|
+
if (e.action === "impression") byDateMap[dateStr].impressions++;
|
|
245
|
+
if (e.action === "click") byDateMap[dateStr].clicks++;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
const byDate = Object.entries(byDateMap).map(([date, data]) => ({
|
|
249
|
+
date,
|
|
250
|
+
impressions: data.impressions,
|
|
251
|
+
clicks: data.clicks
|
|
252
|
+
}));
|
|
253
|
+
return {
|
|
254
|
+
broadcastId,
|
|
255
|
+
title: broadcast.title,
|
|
256
|
+
status: broadcast.status,
|
|
257
|
+
impressions,
|
|
258
|
+
clicks,
|
|
259
|
+
dismissals,
|
|
260
|
+
ctr: impressions > 0 ? clicks / impressions : 0,
|
|
261
|
+
byPlatform,
|
|
262
|
+
byProject,
|
|
263
|
+
byDate
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
async function getOverallAnalytics(startDate, endDate) {
|
|
267
|
+
const db = analytics.getSharedFeaturesDb();
|
|
268
|
+
const eventsQuery = firestore.query(
|
|
269
|
+
firestore.collection(db, COLLECTION_BROADCAST_EVENTS),
|
|
270
|
+
firestore.where("timestamp", ">=", firestore.Timestamp.fromDate(startDate)),
|
|
271
|
+
firestore.where("timestamp", "<=", firestore.Timestamp.fromDate(endDate))
|
|
272
|
+
);
|
|
273
|
+
const eventsSnapshot = await firestore.getDocs(eventsQuery);
|
|
274
|
+
const events = eventsSnapshot.docs.map((d) => d.data());
|
|
275
|
+
const totalSent = events.filter((e) => e.action === "impression").length;
|
|
276
|
+
const totalRead = events.filter((e) => e.action === "impression").length;
|
|
277
|
+
const totalClicked = events.filter((e) => e.action === "click").length;
|
|
278
|
+
const byCategory = {
|
|
279
|
+
system: { sent: 0, read: 0, clicked: 0 },
|
|
280
|
+
account: { sent: 0, read: 0, clicked: 0 },
|
|
281
|
+
activity: { sent: 0, read: 0, clicked: 0 },
|
|
282
|
+
report: { sent: 0, read: 0, clicked: 0 },
|
|
283
|
+
promotional: { sent: 0, read: 0, clicked: 0 },
|
|
284
|
+
social: { sent: 0, read: 0, clicked: 0 }
|
|
285
|
+
};
|
|
286
|
+
const byType = {
|
|
287
|
+
info: { sent: 0, read: 0, clicked: 0 },
|
|
288
|
+
success: { sent: 0, read: 0, clicked: 0 },
|
|
289
|
+
warning: { sent: 0, read: 0, clicked: 0 },
|
|
290
|
+
error: { sent: 0, read: 0, clicked: 0 },
|
|
291
|
+
reminder: { sent: 0, read: 0, clicked: 0 },
|
|
292
|
+
milestone: { sent: 0, read: 0, clicked: 0 },
|
|
293
|
+
announcement: { sent: 0, read: 0, clicked: 0 }
|
|
294
|
+
};
|
|
295
|
+
const byDateMap = {};
|
|
296
|
+
events.forEach((e) => {
|
|
297
|
+
const dateStr = e.timestamp.toDate().toISOString().split("T")[0];
|
|
298
|
+
if (dateStr) {
|
|
299
|
+
if (!byDateMap[dateStr]) {
|
|
300
|
+
byDateMap[dateStr] = { sent: 0, read: 0, clicked: 0 };
|
|
301
|
+
}
|
|
302
|
+
if (e.action === "impression") {
|
|
303
|
+
byDateMap[dateStr].sent++;
|
|
304
|
+
byDateMap[dateStr].read++;
|
|
305
|
+
}
|
|
306
|
+
if (e.action === "click") byDateMap[dateStr].clicked++;
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
const byDate = Object.entries(byDateMap).map(([date, data]) => ({ date, ...data })).sort((a, b) => a.date.localeCompare(b.date));
|
|
310
|
+
return {
|
|
311
|
+
totalSent,
|
|
312
|
+
totalRead,
|
|
313
|
+
totalClicked,
|
|
314
|
+
readRate: totalSent > 0 ? totalRead / totalSent : 0,
|
|
315
|
+
clickRate: totalSent > 0 ? totalClicked / totalSent : 0,
|
|
316
|
+
byCategory,
|
|
317
|
+
byType,
|
|
318
|
+
byDate
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
const adminNotificationService = {
|
|
322
|
+
// Broadcasts
|
|
323
|
+
createBroadcast,
|
|
324
|
+
updateBroadcast,
|
|
325
|
+
deleteBroadcast,
|
|
326
|
+
getAllBroadcasts,
|
|
327
|
+
getBroadcastsByStatus,
|
|
328
|
+
getBroadcastById,
|
|
329
|
+
publishBroadcast,
|
|
330
|
+
scheduleBroadcast,
|
|
331
|
+
pauseBroadcast,
|
|
332
|
+
endBroadcast,
|
|
333
|
+
// Templates
|
|
334
|
+
createTemplate,
|
|
335
|
+
updateTemplate,
|
|
336
|
+
deleteTemplate,
|
|
337
|
+
getAllTemplates,
|
|
338
|
+
getTemplateById,
|
|
339
|
+
getFirestoreTemplateByEventType,
|
|
340
|
+
// Analytics
|
|
341
|
+
getBroadcastAnalytics,
|
|
342
|
+
getOverallAnalytics
|
|
343
|
+
};
|
|
344
|
+
exports.adminNotificationService = adminNotificationService;
|
|
345
|
+
exports.createBroadcast = createBroadcast;
|
|
346
|
+
exports.createTemplate = createTemplate;
|
|
347
|
+
exports.deleteBroadcast = deleteBroadcast;
|
|
348
|
+
exports.deleteTemplate = deleteTemplate;
|
|
349
|
+
exports.endBroadcast = endBroadcast;
|
|
350
|
+
exports.getAllBroadcasts = getAllBroadcasts;
|
|
351
|
+
exports.getAllTemplates = getAllTemplates;
|
|
352
|
+
exports.getBroadcastAnalytics = getBroadcastAnalytics;
|
|
353
|
+
exports.getBroadcastsByStatus = getBroadcastsByStatus;
|
|
354
|
+
exports.getFirestoreTemplateByEventType = getFirestoreTemplateByEventType;
|
|
355
|
+
exports.getOverallAnalytics = getOverallAnalytics;
|
|
356
|
+
exports.getTemplateById = getTemplateById;
|
|
357
|
+
exports.pauseBroadcast = pauseBroadcast;
|
|
358
|
+
exports.publishBroadcast = publishBroadcast;
|
|
359
|
+
exports.scheduleBroadcast = scheduleBroadcast;
|
|
360
|
+
exports.updateBroadcast = updateBroadcast;
|
|
361
|
+
exports.updateTemplate = updateTemplate;
|
|
362
|
+
//# sourceMappingURL=admin-notifications-D9n9h-eY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-notifications-D9n9h-eY.cjs","sources":["../src/services/admin-notifications.ts"],"sourcesContent":["/**\n * Admin Notifications Service\n *\n * Service for managing broadcasts and templates from the admin panel.\n * Used in aoneahsan.com admin panel to manage cross-project notifications.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n doc,\n getDocs,\n getDoc,\n updateDoc,\n deleteDoc,\n addDoc,\n query,\n where,\n orderBy,\n serverTimestamp,\n Timestamp,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport type {\n BroadcastNotification,\n BroadcastStatus,\n CreateBroadcastInput,\n UpdateBroadcastInput,\n NotificationTemplate,\n CreateTemplateInput,\n BroadcastAnalytics,\n NotificationAnalytics,\n} from '../types/notifications';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst COLLECTION_BROADCASTS = 'zaions_broadcasts';\nconst COLLECTION_TEMPLATES = 'zaions_notification_templates';\nconst COLLECTION_BROADCAST_EVENTS = 'zaions_broadcast_events';\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Convert Firestore document to BroadcastNotification\n */\nfunction docToBroadcast(\n docId: string,\n data: Record<string, unknown>\n): BroadcastNotification {\n return {\n id: docId,\n title: data.title as string,\n message: data.message as string,\n type: data.type as BroadcastNotification['type'],\n category: data.category as BroadcastNotification['category'],\n isRead: false,\n isImportant: data.isImportant as boolean | undefined,\n actionUrl: data.actionUrl as string | undefined,\n actionText: data.actionText as string | undefined,\n createdAt: data.createdAt as Timestamp,\n metadata: data.metadata as Record<string, unknown> | undefined,\n targetProjects: (data.targetProjects as string[]) || [],\n targetPlatforms: (data.targetPlatforms as BroadcastNotification['targetPlatforms']) || [],\n targetAudience: (data.targetAudience as BroadcastNotification['targetAudience']) || 'all',\n status: data.status as BroadcastStatus,\n startDate: data.startDate as Timestamp,\n endDate: data.endDate as Timestamp | null | undefined,\n priority: (data.priority as number) || 50,\n dismissible: data.dismissible !== false,\n variant: (data.variant as BroadcastNotification['variant']) || 'banner',\n impressions: (data.impressions as number) || 0,\n clicks: (data.clicks as number) || 0,\n createdBy: data.createdBy as string,\n updatedBy: data.updatedBy as string | undefined,\n };\n}\n\n/**\n * Convert Firestore document to NotificationTemplate\n */\nfunction docToTemplate(\n docId: string,\n data: Record<string, unknown>\n): NotificationTemplate {\n return {\n id: docId,\n name: data.name as string,\n eventType: data.eventType as string,\n category: data.category as NotificationTemplate['category'],\n title: data.title as string,\n message: data.message as string,\n variables: (data.variables as string[]) || [],\n type: data.type as NotificationTemplate['type'],\n isImportant: data.isImportant as boolean,\n actionUrl: data.actionUrl as string | undefined,\n actionText: data.actionText as string | undefined,\n enabled: data.enabled !== false,\n createdAt: (data.createdAt as Timestamp)?.toDate() || new Date(),\n updatedAt: (data.updatedAt as Timestamp)?.toDate() || new Date(),\n };\n}\n\n// ============================================================================\n// BROADCAST CRUD\n// ============================================================================\n\n/**\n * Create a new broadcast\n */\nexport async function createBroadcast(\n input: CreateBroadcastInput,\n adminUserId: string\n): Promise<string> {\n const db = getSharedFeaturesDb();\n\n const broadcastData = {\n ...input,\n status: 'draft' as BroadcastStatus,\n isRead: false,\n impressions: 0,\n clicks: 0,\n createdBy: adminUserId,\n createdAt: serverTimestamp(),\n startDate: Timestamp.fromDate(input.startDate),\n endDate: input.endDate ? Timestamp.fromDate(input.endDate) : null,\n };\n\n const docRef = await addDoc(\n collection(db, COLLECTION_BROADCASTS),\n broadcastData\n );\n\n return docRef.id;\n}\n\n/**\n * Update an existing broadcast\n */\nexport async function updateBroadcast(\n input: UpdateBroadcastInput,\n adminUserId: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n\n const updateData: Record<string, unknown> = {\n ...input,\n updatedBy: adminUserId,\n updatedAt: serverTimestamp(),\n };\n\n // Convert dates if provided\n if (input.startDate) {\n updateData.startDate = Timestamp.fromDate(input.startDate);\n }\n if (input.endDate !== undefined) {\n updateData.endDate = input.endDate ? Timestamp.fromDate(input.endDate) : null;\n }\n\n // Remove id from update data\n delete updateData.id;\n\n await updateDoc(doc(db, COLLECTION_BROADCASTS, input.id), updateData);\n}\n\n/**\n * Delete a broadcast\n */\nexport async function deleteBroadcast(broadcastId: string): Promise<void> {\n const db = getSharedFeaturesDb();\n await deleteDoc(doc(db, COLLECTION_BROADCASTS, broadcastId));\n}\n\n/**\n * Get all broadcasts (for admin listing)\n */\nexport async function getAllBroadcasts(): Promise<BroadcastNotification[]> {\n const db = getSharedFeaturesDb();\n\n const q = query(\n collection(db, COLLECTION_BROADCASTS),\n orderBy('createdAt', 'desc')\n );\n\n const snapshot = await getDocs(q);\n return snapshot.docs.map((d) => docToBroadcast(d.id, d.data()));\n}\n\n/**\n * Get broadcasts by status\n */\nexport async function getBroadcastsByStatus(\n status: BroadcastStatus\n): Promise<BroadcastNotification[]> {\n const db = getSharedFeaturesDb();\n\n const q = query(\n collection(db, COLLECTION_BROADCASTS),\n where('status', '==', status),\n orderBy('createdAt', 'desc')\n );\n\n const snapshot = await getDocs(q);\n return snapshot.docs.map((d) => docToBroadcast(d.id, d.data()));\n}\n\n/**\n * Get a single broadcast by ID\n */\nexport async function getBroadcastById(\n broadcastId: string\n): Promise<BroadcastNotification | null> {\n const db = getSharedFeaturesDb();\n const docSnap = await getDoc(doc(db, COLLECTION_BROADCASTS, broadcastId));\n\n if (!docSnap.exists()) return null;\n return docToBroadcast(docSnap.id, docSnap.data());\n}\n\n// ============================================================================\n// BROADCAST STATUS MANAGEMENT\n// ============================================================================\n\n/**\n * Publish a draft broadcast (set to active)\n */\nexport async function publishBroadcast(\n broadcastId: string,\n adminUserId: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n\n await updateDoc(doc(db, COLLECTION_BROADCASTS, broadcastId), {\n status: 'active',\n updatedBy: adminUserId,\n updatedAt: serverTimestamp(),\n });\n}\n\n/**\n * Schedule a broadcast for later\n */\nexport async function scheduleBroadcast(\n broadcastId: string,\n scheduledDate: Date,\n adminUserId: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n\n await updateDoc(doc(db, COLLECTION_BROADCASTS, broadcastId), {\n status: 'scheduled',\n startDate: Timestamp.fromDate(scheduledDate),\n updatedBy: adminUserId,\n updatedAt: serverTimestamp(),\n });\n}\n\n/**\n * Pause an active broadcast\n */\nexport async function pauseBroadcast(\n broadcastId: string,\n adminUserId: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n\n await updateDoc(doc(db, COLLECTION_BROADCASTS, broadcastId), {\n status: 'draft', // Move back to draft\n updatedBy: adminUserId,\n updatedAt: serverTimestamp(),\n });\n}\n\n/**\n * End a broadcast\n */\nexport async function endBroadcast(\n broadcastId: string,\n adminUserId: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n\n await updateDoc(doc(db, COLLECTION_BROADCASTS, broadcastId), {\n status: 'ended',\n endDate: serverTimestamp(),\n updatedBy: adminUserId,\n updatedAt: serverTimestamp(),\n });\n}\n\n// ============================================================================\n// TEMPLATE CRUD\n// ============================================================================\n\n/**\n * Create a new template\n */\nexport async function createTemplate(\n input: CreateTemplateInput\n): Promise<string> {\n const db = getSharedFeaturesDb();\n\n const templateData = {\n ...input,\n createdAt: serverTimestamp(),\n updatedAt: serverTimestamp(),\n };\n\n const docRef = await addDoc(\n collection(db, COLLECTION_TEMPLATES),\n templateData\n );\n\n return docRef.id;\n}\n\n/**\n * Update an existing template\n */\nexport async function updateTemplate(\n templateId: string,\n input: Partial<CreateTemplateInput>\n): Promise<void> {\n const db = getSharedFeaturesDb();\n\n await updateDoc(doc(db, COLLECTION_TEMPLATES, templateId), {\n ...input,\n updatedAt: serverTimestamp(),\n });\n}\n\n/**\n * Delete a template\n */\nexport async function deleteTemplate(templateId: string): Promise<void> {\n const db = getSharedFeaturesDb();\n await deleteDoc(doc(db, COLLECTION_TEMPLATES, templateId));\n}\n\n/**\n * Get all templates\n */\nexport async function getAllTemplates(): Promise<NotificationTemplate[]> {\n const db = getSharedFeaturesDb();\n\n const q = query(\n collection(db, COLLECTION_TEMPLATES),\n orderBy('name', 'asc')\n );\n\n const snapshot = await getDocs(q);\n return snapshot.docs.map((d) => docToTemplate(d.id, d.data()));\n}\n\n/**\n * Get template by ID\n */\nexport async function getTemplateById(\n templateId: string\n): Promise<NotificationTemplate | null> {\n const db = getSharedFeaturesDb();\n const docSnap = await getDoc(doc(db, COLLECTION_TEMPLATES, templateId));\n\n if (!docSnap.exists()) return null;\n return docToTemplate(docSnap.id, docSnap.data());\n}\n\n/**\n * Get template by event type from Firestore\n */\nexport async function getFirestoreTemplateByEventType(\n eventType: string\n): Promise<NotificationTemplate | null> {\n const db = getSharedFeaturesDb();\n\n const q = query(\n collection(db, COLLECTION_TEMPLATES),\n where('eventType', '==', eventType)\n );\n\n const snapshot = await getDocs(q);\n if (snapshot.empty) return null;\n\n const docSnap = snapshot.docs[0];\n if (!docSnap) return null;\n\n return docToTemplate(docSnap.id, docSnap.data());\n}\n\n// ============================================================================\n// ANALYTICS\n// ============================================================================\n\n/**\n * Get analytics for a specific broadcast\n */\nexport async function getBroadcastAnalytics(\n broadcastId: string\n): Promise<BroadcastAnalytics | null> {\n const db = getSharedFeaturesDb();\n\n // Get broadcast\n const broadcast = await getBroadcastById(broadcastId);\n if (!broadcast) return null;\n\n // Get events\n const eventsQuery = query(\n collection(db, COLLECTION_BROADCAST_EVENTS),\n where('broadcastId', '==', broadcastId)\n );\n\n const eventsSnapshot = await getDocs(eventsQuery);\n const events = eventsSnapshot.docs.map((d) => d.data());\n\n // Calculate analytics\n const impressions = events.filter((e) => e.action === 'impression').length;\n const clicks = events.filter((e) => e.action === 'click').length;\n const dismissals = events.filter((e) => e.action === 'dismiss').length;\n\n // Group by platform\n const byPlatform: BroadcastAnalytics['byPlatform'] = {\n web: { impressions: 0, clicks: 0 },\n android: { impressions: 0, clicks: 0 },\n ios: { impressions: 0, clicks: 0 },\n };\n\n events.forEach((e) => {\n const platform = e.platform as keyof typeof byPlatform;\n if (byPlatform[platform]) {\n if (e.action === 'impression') byPlatform[platform].impressions++;\n if (e.action === 'click') byPlatform[platform].clicks++;\n }\n });\n\n // Group by project\n const byProject: BroadcastAnalytics['byProject'] = {};\n events.forEach((e) => {\n const projectId = e.projectId as string;\n if (!byProject[projectId]) {\n byProject[projectId] = { impressions: 0, clicks: 0 };\n }\n if (e.action === 'impression') byProject[projectId].impressions++;\n if (e.action === 'click') byProject[projectId].clicks++;\n });\n\n // Group by date\n const byDateMap: Record<string, { impressions: number; clicks: number }> = {};\n events.forEach((e) => {\n const dateStr = (e.timestamp as Timestamp).toDate().toISOString().split('T')[0];\n if (dateStr) {\n if (!byDateMap[dateStr]) {\n byDateMap[dateStr] = { impressions: 0, clicks: 0 };\n }\n if (e.action === 'impression') byDateMap[dateStr].impressions++;\n if (e.action === 'click') byDateMap[dateStr].clicks++;\n }\n });\n\n const byDate = Object.entries(byDateMap).map(([date, data]) => ({\n date,\n impressions: data.impressions,\n clicks: data.clicks,\n }));\n\n return {\n broadcastId,\n title: broadcast.title,\n status: broadcast.status,\n impressions,\n clicks,\n dismissals,\n ctr: impressions > 0 ? clicks / impressions : 0,\n byPlatform,\n byProject,\n byDate,\n };\n}\n\n/**\n * Get overall notification analytics\n */\nexport async function getOverallAnalytics(\n startDate: Date,\n endDate: Date\n): Promise<NotificationAnalytics> {\n const db = getSharedFeaturesDb();\n\n // Get all broadcast events in date range\n const eventsQuery = query(\n collection(db, COLLECTION_BROADCAST_EVENTS),\n where('timestamp', '>=', Timestamp.fromDate(startDate)),\n where('timestamp', '<=', Timestamp.fromDate(endDate))\n );\n\n const eventsSnapshot = await getDocs(eventsQuery);\n const events = eventsSnapshot.docs.map((d) => d.data());\n\n // Calculate totals\n const totalSent = events.filter((e) => e.action === 'impression').length;\n const totalRead = events.filter((e) => e.action === 'impression').length; // Impressions = read for broadcasts\n const totalClicked = events.filter((e) => e.action === 'click').length;\n\n // Initialize category and type breakdowns\n const byCategory: NotificationAnalytics['byCategory'] = {\n system: { sent: 0, read: 0, clicked: 0 },\n account: { sent: 0, read: 0, clicked: 0 },\n activity: { sent: 0, read: 0, clicked: 0 },\n report: { sent: 0, read: 0, clicked: 0 },\n promotional: { sent: 0, read: 0, clicked: 0 },\n social: { sent: 0, read: 0, clicked: 0 },\n };\n\n const byType: NotificationAnalytics['byType'] = {\n info: { sent: 0, read: 0, clicked: 0 },\n success: { sent: 0, read: 0, clicked: 0 },\n warning: { sent: 0, read: 0, clicked: 0 },\n error: { sent: 0, read: 0, clicked: 0 },\n reminder: { sent: 0, read: 0, clicked: 0 },\n milestone: { sent: 0, read: 0, clicked: 0 },\n announcement: { sent: 0, read: 0, clicked: 0 },\n };\n\n // Group by date\n const byDateMap: Record<string, { sent: number; read: number; clicked: number }> = {};\n events.forEach((e) => {\n const dateStr = (e.timestamp as Timestamp).toDate().toISOString().split('T')[0];\n if (dateStr) {\n if (!byDateMap[dateStr]) {\n byDateMap[dateStr] = { sent: 0, read: 0, clicked: 0 };\n }\n if (e.action === 'impression') {\n byDateMap[dateStr].sent++;\n byDateMap[dateStr].read++;\n }\n if (e.action === 'click') byDateMap[dateStr].clicked++;\n }\n });\n\n const byDate = Object.entries(byDateMap)\n .map(([date, data]) => ({ date, ...data }))\n .sort((a, b) => a.date.localeCompare(b.date));\n\n return {\n totalSent,\n totalRead,\n totalClicked,\n readRate: totalSent > 0 ? totalRead / totalSent : 0,\n clickRate: totalSent > 0 ? totalClicked / totalSent : 0,\n byCategory,\n byType,\n byDate,\n };\n}\n\n// ============================================================================\n// EXPORT SERVICE OBJECT\n// ============================================================================\n\nexport const adminNotificationService = {\n // Broadcasts\n createBroadcast,\n updateBroadcast,\n deleteBroadcast,\n getAllBroadcasts,\n getBroadcastsByStatus,\n getBroadcastById,\n publishBroadcast,\n scheduleBroadcast,\n pauseBroadcast,\n endBroadcast,\n\n // Templates\n createTemplate,\n updateTemplate,\n deleteTemplate,\n getAllTemplates,\n getTemplateById,\n getFirestoreTemplateByEventType,\n\n // Analytics\n getBroadcastAnalytics,\n getOverallAnalytics,\n};\n\nexport default adminNotificationService;\n"],"names":["getSharedFeaturesDb","serverTimestamp","Timestamp","addDoc","collection","updateDoc","doc","deleteDoc","query","orderBy","getDocs","where","getDoc"],"mappings":";;;AAuCA,MAAM,wBAAwB;AAC9B,MAAM,uBAAuB;AAC7B,MAAM,8BAA8B;AASpC,SAAS,eACP,OACA,MACuB;AACvB,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK;AAAA,IACd,MAAM,KAAK;AAAA,IACX,UAAU,KAAK;AAAA,IACf,QAAQ;AAAA,IACR,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB,YAAY,KAAK;AAAA,IACjB,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,IACf,gBAAiB,KAAK,kBAA+B,CAAA;AAAA,IACrD,iBAAkB,KAAK,mBAAgE,CAAA;AAAA,IACvF,gBAAiB,KAAK,kBAA8D;AAAA,IACpF,QAAQ,KAAK;AAAA,IACb,WAAW,KAAK;AAAA,IAChB,SAAS,KAAK;AAAA,IACd,UAAW,KAAK,YAAuB;AAAA,IACvC,aAAa,KAAK,gBAAgB;AAAA,IAClC,SAAU,KAAK,WAAgD;AAAA,IAC/D,aAAc,KAAK,eAA0B;AAAA,IAC7C,QAAS,KAAK,UAAqB;AAAA,IACnC,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,EAAA;AAEpB;AAKA,SAAS,cACP,OACA,MACsB;AACtB,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,KAAK;AAAA,IACX,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK;AAAA,IACd,WAAY,KAAK,aAA0B,CAAA;AAAA,IAC3C,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB,YAAY,KAAK;AAAA,IACjB,SAAS,KAAK,YAAY;AAAA,IAC1B,WAAY,KAAK,WAAyB,OAAA,yBAAgB,KAAA;AAAA,IAC1D,WAAY,KAAK,WAAyB,OAAA,yBAAgB,KAAA;AAAA,EAAK;AAEnE;AASA,eAAsB,gBACpB,OACA,aACiB;AACjB,QAAM,KAAKA,UAAAA,oBAAA;AAEX,QAAM,gBAAgB;AAAA,IACpB,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,WAAWC,UAAAA,gBAAA;AAAA,IACX,WAAWC,UAAAA,UAAU,SAAS,MAAM,SAAS;AAAA,IAC7C,SAAS,MAAM,UAAUA,UAAAA,UAAU,SAAS,MAAM,OAAO,IAAI;AAAA,EAAA;AAG/D,QAAM,SAAS,MAAMC,UAAAA;AAAAA,IACnBC,UAAAA,WAAW,IAAI,qBAAqB;AAAA,IACpC;AAAA,EAAA;AAGF,SAAO,OAAO;AAChB;AAKA,eAAsB,gBACpB,OACA,aACe;AACf,QAAM,KAAKJ,UAAAA,oBAAA;AAEX,QAAM,aAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,WAAW;AAAA,IACX,WAAWC,UAAAA,gBAAA;AAAA,EAAgB;AAI7B,MAAI,MAAM,WAAW;AACnB,eAAW,YAAYC,UAAAA,UAAU,SAAS,MAAM,SAAS;AAAA,EAC3D;AACA,MAAI,MAAM,YAAY,QAAW;AAC/B,eAAW,UAAU,MAAM,UAAUA,UAAAA,UAAU,SAAS,MAAM,OAAO,IAAI;AAAA,EAC3E;AAGA,SAAO,WAAW;AAElB,QAAMG,UAAAA,UAAUC,UAAAA,IAAI,IAAI,uBAAuB,MAAM,EAAE,GAAG,UAAU;AACtE;AAKA,eAAsB,gBAAgB,aAAoC;AACxE,QAAM,KAAKN,UAAAA,oBAAA;AACX,QAAMO,UAAAA,UAAUD,UAAAA,IAAI,IAAI,uBAAuB,WAAW,CAAC;AAC7D;AAKA,eAAsB,mBAAqD;AACzE,QAAM,KAAKN,UAAAA,oBAAA;AAEX,QAAM,IAAIQ,UAAAA;AAAAA,IACRJ,UAAAA,WAAW,IAAI,qBAAqB;AAAA,IACpCK,UAAAA,QAAQ,aAAa,MAAM;AAAA,EAAA;AAG7B,QAAM,WAAW,MAAMC,UAAAA,QAAQ,CAAC;AAChC,SAAO,SAAS,KAAK,IAAI,CAAC,MAAM,eAAe,EAAE,IAAI,EAAE,KAAA,CAAM,CAAC;AAChE;AAKA,eAAsB,sBACpB,QACkC;AAClC,QAAM,KAAKV,UAAAA,oBAAA;AAEX,QAAM,IAAIQ,UAAAA;AAAAA,IACRJ,UAAAA,WAAW,IAAI,qBAAqB;AAAA,IACpCO,gBAAM,UAAU,MAAM,MAAM;AAAA,IAC5BF,UAAAA,QAAQ,aAAa,MAAM;AAAA,EAAA;AAG7B,QAAM,WAAW,MAAMC,UAAAA,QAAQ,CAAC;AAChC,SAAO,SAAS,KAAK,IAAI,CAAC,MAAM,eAAe,EAAE,IAAI,EAAE,KAAA,CAAM,CAAC;AAChE;AAKA,eAAsB,iBACpB,aACuC;AACvC,QAAM,KAAKV,UAAAA,oBAAA;AACX,QAAM,UAAU,MAAMY,iBAAON,UAAAA,IAAI,IAAI,uBAAuB,WAAW,CAAC;AAExE,MAAI,CAAC,QAAQ,OAAA,EAAU,QAAO;AAC9B,SAAO,eAAe,QAAQ,IAAI,QAAQ,MAAM;AAClD;AASA,eAAsB,iBACpB,aACA,aACe;AACf,QAAM,KAAKN,UAAAA,oBAAA;AAEX,QAAMK,UAAAA,UAAUC,UAAAA,IAAI,IAAI,uBAAuB,WAAW,GAAG;AAAA,IAC3D,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,WAAWL,UAAAA,gBAAA;AAAA,EAAgB,CAC5B;AACH;AAKA,eAAsB,kBACpB,aACA,eACA,aACe;AACf,QAAM,KAAKD,UAAAA,oBAAA;AAEX,QAAMK,UAAAA,UAAUC,UAAAA,IAAI,IAAI,uBAAuB,WAAW,GAAG;AAAA,IAC3D,QAAQ;AAAA,IACR,WAAWJ,UAAAA,UAAU,SAAS,aAAa;AAAA,IAC3C,WAAW;AAAA,IACX,WAAWD,UAAAA,gBAAA;AAAA,EAAgB,CAC5B;AACH;AAKA,eAAsB,eACpB,aACA,aACe;AACf,QAAM,KAAKD,UAAAA,oBAAA;AAEX,QAAMK,UAAAA,UAAUC,UAAAA,IAAI,IAAI,uBAAuB,WAAW,GAAG;AAAA,IAC3D,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA,IACX,WAAWL,UAAAA,gBAAA;AAAA,EAAgB,CAC5B;AACH;AAKA,eAAsB,aACpB,aACA,aACe;AACf,QAAM,KAAKD,UAAAA,oBAAA;AAEX,QAAMK,UAAAA,UAAUC,UAAAA,IAAI,IAAI,uBAAuB,WAAW,GAAG;AAAA,IAC3D,QAAQ;AAAA,IACR,SAASL,UAAAA,gBAAA;AAAA,IACT,WAAW;AAAA,IACX,WAAWA,UAAAA,gBAAA;AAAA,EAAgB,CAC5B;AACH;AASA,eAAsB,eACpB,OACiB;AACjB,QAAM,KAAKD,UAAAA,oBAAA;AAEX,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,WAAWC,UAAAA,gBAAA;AAAA,IACX,WAAWA,UAAAA,gBAAA;AAAA,EAAgB;AAG7B,QAAM,SAAS,MAAME,UAAAA;AAAAA,IACnBC,UAAAA,WAAW,IAAI,oBAAoB;AAAA,IACnC;AAAA,EAAA;AAGF,SAAO,OAAO;AAChB;AAKA,eAAsB,eACpB,YACA,OACe;AACf,QAAM,KAAKJ,UAAAA,oBAAA;AAEX,QAAMK,UAAAA,UAAUC,UAAAA,IAAI,IAAI,sBAAsB,UAAU,GAAG;AAAA,IACzD,GAAG;AAAA,IACH,WAAWL,UAAAA,gBAAA;AAAA,EAAgB,CAC5B;AACH;AAKA,eAAsB,eAAe,YAAmC;AACtE,QAAM,KAAKD,UAAAA,oBAAA;AACX,QAAMO,UAAAA,UAAUD,UAAAA,IAAI,IAAI,sBAAsB,UAAU,CAAC;AAC3D;AAKA,eAAsB,kBAAmD;AACvE,QAAM,KAAKN,UAAAA,oBAAA;AAEX,QAAM,IAAIQ,UAAAA;AAAAA,IACRJ,UAAAA,WAAW,IAAI,oBAAoB;AAAA,IACnCK,UAAAA,QAAQ,QAAQ,KAAK;AAAA,EAAA;AAGvB,QAAM,WAAW,MAAMC,UAAAA,QAAQ,CAAC;AAChC,SAAO,SAAS,KAAK,IAAI,CAAC,MAAM,cAAc,EAAE,IAAI,EAAE,KAAA,CAAM,CAAC;AAC/D;AAKA,eAAsB,gBACpB,YACsC;AACtC,QAAM,KAAKV,UAAAA,oBAAA;AACX,QAAM,UAAU,MAAMY,iBAAON,UAAAA,IAAI,IAAI,sBAAsB,UAAU,CAAC;AAEtE,MAAI,CAAC,QAAQ,OAAA,EAAU,QAAO;AAC9B,SAAO,cAAc,QAAQ,IAAI,QAAQ,MAAM;AACjD;AAKA,eAAsB,gCACpB,WACsC;AACtC,QAAM,KAAKN,UAAAA,oBAAA;AAEX,QAAM,IAAIQ,UAAAA;AAAAA,IACRJ,UAAAA,WAAW,IAAI,oBAAoB;AAAA,IACnCO,gBAAM,aAAa,MAAM,SAAS;AAAA,EAAA;AAGpC,QAAM,WAAW,MAAMD,UAAAA,QAAQ,CAAC;AAChC,MAAI,SAAS,MAAO,QAAO;AAE3B,QAAM,UAAU,SAAS,KAAK,CAAC;AAC/B,MAAI,CAAC,QAAS,QAAO;AAErB,SAAO,cAAc,QAAQ,IAAI,QAAQ,MAAM;AACjD;AASA,eAAsB,sBACpB,aACoC;AACpC,QAAM,KAAKV,UAAAA,oBAAA;AAGX,QAAM,YAAY,MAAM,iBAAiB,WAAW;AACpD,MAAI,CAAC,UAAW,QAAO;AAGvB,QAAM,cAAcQ,UAAAA;AAAAA,IAClBJ,UAAAA,WAAW,IAAI,2BAA2B;AAAA,IAC1CO,gBAAM,eAAe,MAAM,WAAW;AAAA,EAAA;AAGxC,QAAM,iBAAiB,MAAMD,UAAAA,QAAQ,WAAW;AAChD,QAAM,SAAS,eAAe,KAAK,IAAI,CAAC,MAAM,EAAE,MAAM;AAGtD,QAAM,cAAc,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY,EAAE;AACpE,QAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,EAAE;AAC1D,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AAGhE,QAAM,aAA+C;AAAA,IACnD,KAAK,EAAE,aAAa,GAAG,QAAQ,EAAA;AAAA,IAC/B,SAAS,EAAE,aAAa,GAAG,QAAQ,EAAA;AAAA,IACnC,KAAK,EAAE,aAAa,GAAG,QAAQ,EAAA;AAAA,EAAE;AAGnC,SAAO,QAAQ,CAAC,MAAM;AACpB,UAAM,WAAW,EAAE;AACnB,QAAI,WAAW,QAAQ,GAAG;AACxB,UAAI,EAAE,WAAW,aAAc,YAAW,QAAQ,EAAE;AACpD,UAAI,EAAE,WAAW,QAAS,YAAW,QAAQ,EAAE;AAAA,IACjD;AAAA,EACF,CAAC;AAGD,QAAM,YAA6C,CAAA;AACnD,SAAO,QAAQ,CAAC,MAAM;AACpB,UAAM,YAAY,EAAE;AACpB,QAAI,CAAC,UAAU,SAAS,GAAG;AACzB,gBAAU,SAAS,IAAI,EAAE,aAAa,GAAG,QAAQ,EAAA;AAAA,IACnD;AACA,QAAI,EAAE,WAAW,aAAc,WAAU,SAAS,EAAE;AACpD,QAAI,EAAE,WAAW,QAAS,WAAU,SAAS,EAAE;AAAA,EACjD,CAAC;AAGD,QAAM,YAAqE,CAAA;AAC3E,SAAO,QAAQ,CAAC,MAAM;AACpB,UAAM,UAAW,EAAE,UAAwB,OAAA,EAAS,cAAc,MAAM,GAAG,EAAE,CAAC;AAC9E,QAAI,SAAS;AACX,UAAI,CAAC,UAAU,OAAO,GAAG;AACvB,kBAAU,OAAO,IAAI,EAAE,aAAa,GAAG,QAAQ,EAAA;AAAA,MACjD;AACA,UAAI,EAAE,WAAW,aAAc,WAAU,OAAO,EAAE;AAClD,UAAI,EAAE,WAAW,QAAS,WAAU,OAAO,EAAE;AAAA,IAC/C;AAAA,EACF,CAAC;AAED,QAAM,SAAS,OAAO,QAAQ,SAAS,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO;AAAA,IAC9D;AAAA,IACA,aAAa,KAAK;AAAA,IAClB,QAAQ,KAAK;AAAA,EAAA,EACb;AAEF,SAAO;AAAA,IACL;AAAA,IACA,OAAO,UAAU;AAAA,IACjB,QAAQ,UAAU;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,cAAc,IAAI,SAAS,cAAc;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAKA,eAAsB,oBACpB,WACA,SACgC;AAChC,QAAM,KAAKV,UAAAA,oBAAA;AAGX,QAAM,cAAcQ,UAAAA;AAAAA,IAClBJ,UAAAA,WAAW,IAAI,2BAA2B;AAAA,IAC1CO,UAAAA,MAAM,aAAa,MAAMT,UAAAA,UAAU,SAAS,SAAS,CAAC;AAAA,IACtDS,UAAAA,MAAM,aAAa,MAAMT,UAAAA,UAAU,SAAS,OAAO,CAAC;AAAA,EAAA;AAGtD,QAAM,iBAAiB,MAAMQ,UAAAA,QAAQ,WAAW;AAChD,QAAM,SAAS,eAAe,KAAK,IAAI,CAAC,MAAM,EAAE,MAAM;AAGtD,QAAM,YAAY,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY,EAAE;AAClE,QAAM,YAAY,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY,EAAE;AAClE,QAAM,eAAe,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,EAAE;AAGhE,QAAM,aAAkD;AAAA,IACtD,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACrC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACtC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACvC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACrC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IAC1C,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,EAAE;AAGzC,QAAM,SAA0C;AAAA,IAC9C,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACnC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACtC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACtC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACpC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACvC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,IACxC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,EAAE;AAI/C,QAAM,YAA6E,CAAA;AACnF,SAAO,QAAQ,CAAC,MAAM;AACpB,UAAM,UAAW,EAAE,UAAwB,OAAA,EAAS,cAAc,MAAM,GAAG,EAAE,CAAC;AAC9E,QAAI,SAAS;AACX,UAAI,CAAC,UAAU,OAAO,GAAG;AACvB,kBAAU,OAAO,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA;AAAA,MACpD;AACA,UAAI,EAAE,WAAW,cAAc;AAC7B,kBAAU,OAAO,EAAE;AACnB,kBAAU,OAAO,EAAE;AAAA,MACrB;AACA,UAAI,EAAE,WAAW,QAAS,WAAU,OAAO,EAAE;AAAA,IAC/C;AAAA,EACF,CAAC;AAED,QAAM,SAAS,OAAO,QAAQ,SAAS,EACpC,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,EAAE,MAAM,GAAG,KAAA,EAAO,EACzC,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAE9C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,YAAY,IAAI,YAAY,YAAY;AAAA,IAClD,WAAW,YAAY,IAAI,eAAe,YAAY;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAMO,MAAM,2BAA2B;AAAA;AAAA,EAEtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AACF;;;;;;;;;;;;;;;;;;;"}
|