-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathautomations.js
More file actions
394 lines (350 loc) Β· 13.3 KB
/
Copy pathautomations.js
File metadata and controls
394 lines (350 loc) Β· 13.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/* ==========================================
Email Notification Automations
Clock Tower Jaipur | Bar & Kitchen
========================================== */
// ==========================================
// Configuration
// ==========================================
const EMAIL_CONFIG = {
// Re-uses credentials from supabase-config.js
serviceId: typeof EMAILJS_SERVICE_ID !== 'undefined' ? EMAILJS_SERVICE_ID : 'YOUR_SERVICE_ID',
templateId: typeof EMAILJS_TEMPLATE_ID !== 'undefined' ? EMAILJS_TEMPLATE_ID : 'YOUR_TEMPLATE_ID',
publicKey: typeof EMAILJS_PUBLIC_KEY !== 'undefined' ? EMAILJS_PUBLIC_KEY : 'YOUR_PUBLIC_KEY',
ownerEmail: typeof OWNER_EMAIL !== 'undefined' ? OWNER_EMAIL : 'owner@clocktowerjaipur.com',
// Customer confirmation template (create this in EmailJS)
customerTemplateId: 'YOUR_CUSTOMER_TEMPLATE_ID'
};
// ==========================================
// Notification Types
// ==========================================
const NOTIFICATION_TYPES = {
NEW_RESERVATION: 'new_reservation',
CONFIRMATION: 'confirmation',
CANCELLATION: 'cancellation',
REMINDER: 'reminder'
};
// ==========================================
// Email Automation Service
// ==========================================
const EmailAutomation = {
/**
* Initialize EmailJS (call this on page load)
*/
init() {
if (window.emailjs && EMAIL_CONFIG.publicKey !== 'YOUR_PUBLIC_KEY') {
emailjs.init(EMAIL_CONFIG.publicKey);
console.log('β
Email Automation Service initialized');
return true;
}
console.warn('β οΈ EmailJS not available or not configured');
return false;
},
/**
* Send notification when a new reservation is made
* Automatically notifies the owner
* @param {Object} reservation - Reservation data
*/
async onNewReservation(reservation) {
console.log('π New reservation received, triggering automations...');
const results = {
ownerNotification: null,
customerConfirmation: null,
timestamp: new Date().toISOString()
};
// 1. Notify Owner
try {
results.ownerNotification = await this.notifyOwner(reservation);
console.log('β
Owner notification sent');
} catch (error) {
console.error('β Failed to notify owner:', error);
results.ownerNotification = { error: error.message };
}
// 2. Send Customer Confirmation (if email provided)
if (reservation.email) {
try {
results.customerConfirmation = await this.sendCustomerConfirmation(reservation);
console.log('β
Customer confirmation sent');
} catch (error) {
console.error('β Failed to send customer confirmation:', error);
results.customerConfirmation = { error: error.message };
}
}
// 3. Log the automation
this.logAutomation(NOTIFICATION_TYPES.NEW_RESERVATION, reservation, results);
return results;
},
/**
* Send email notification to owner about new reservation
* @param {Object} reservation - Reservation data
*/
async notifyOwner(reservation) {
if (!window.emailjs) {
throw new Error('EmailJS not loaded');
}
const templateParams = {
to_email: EMAIL_CONFIG.ownerEmail,
subject: `π½οΈ New Reservation - ${reservation.name}`,
customer_name: reservation.name,
customer_phone: reservation.phone,
customer_email: reservation.email || 'Not provided',
reservation_date: this.formatDate(reservation.date),
reservation_time: this.formatTime(reservation.time),
guest_count: reservation.guests,
seating_preference: reservation.seating || 'No preference',
special_requests: reservation.message || 'None',
booking_time: new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' })
};
const response = await emailjs.send(
EMAIL_CONFIG.serviceId,
EMAIL_CONFIG.templateId,
templateParams,
EMAIL_CONFIG.publicKey
);
return { success: true, response };
},
/**
* Send confirmation email to customer
* @param {Object} reservation - Reservation data
*/
async sendCustomerConfirmation(reservation) {
if (!window.emailjs) {
throw new Error('EmailJS not loaded');
}
const templateParams = {
to_email: reservation.email,
customer_name: reservation.name,
reservation_date: this.formatDate(reservation.date),
reservation_time: this.formatTime(reservation.time),
guest_count: reservation.guests,
seating_preference: reservation.seating || 'No preference',
restaurant_name: 'Clock Tower Jaipur | Bar & Kitchen',
restaurant_phone: '+917303593339',
restaurant_address: 'Clock Tower, Jaipur, Rajasthan'
};
const response = await emailjs.send(
EMAIL_CONFIG.serviceId,
EMAIL_CONFIG.customerTemplateId,
templateParams,
EMAIL_CONFIG.publicKey
);
return { success: true, response };
},
/**
* Send status update notification to customer
* @param {Object} reservation - Reservation data
* @param {string} newStatus - New status (confirmed, cancelled)
*/
async sendStatusUpdate(reservation, newStatus) {
if (!reservation.email) {
console.log('No customer email - skipping status notification');
return { skipped: true, reason: 'No email provided' };
}
const statusMessages = {
confirmed: {
subject: 'β
Reservation Confirmed!',
message: 'Great news! Your reservation has been confirmed. We look forward to seeing you!'
},
cancelled: {
subject: 'β Reservation Cancelled',
message: 'Your reservation has been cancelled. If this was a mistake, please contact us.'
},
completed: {
subject: 'π Thank You for Visiting!',
message: 'Thank you for dining with us! We hope you had a wonderful experience.'
}
};
const statusInfo = statusMessages[newStatus] || {
subject: 'Reservation Update',
message: `Your reservation status has been updated to: ${newStatus}`
};
const templateParams = {
to_email: reservation.email,
customer_name: reservation.name,
subject: statusInfo.subject,
status_message: statusInfo.message,
reservation_date: this.formatDate(reservation.date),
reservation_time: this.formatTime(reservation.time),
restaurant_name: 'Clock Tower Jaipur | Bar & Kitchen',
restaurant_phone: '+917303593339'
};
try {
const response = await emailjs.send(
EMAIL_CONFIG.serviceId,
EMAIL_CONFIG.customerTemplateId,
templateParams,
EMAIL_CONFIG.publicKey
);
this.logAutomation(newStatus, reservation, { success: true });
return { success: true, response };
} catch (error) {
this.logAutomation(newStatus, reservation, { error: error.message });
throw error;
}
},
// ==========================================
// WhatsApp Fallback (if email fails)
// ==========================================
/**
* Generate WhatsApp notification link as fallback
* @param {Object} reservation - Reservation data
*/
getWhatsAppFallback(reservation) {
const message = encodeURIComponent(
`π½οΈ *New Reservation Alert*\n\n` +
`π€ *Name:* ${reservation.name}\n` +
`π *Phone:* ${reservation.phone}\n` +
`π
*Date:* ${this.formatDate(reservation.date)}\n` +
`π *Time:* ${this.formatTime(reservation.time)}\n` +
`π₯ *Guests:* ${reservation.guests}\n` +
`πͺ *Seating:* ${reservation.seating || 'No preference'}\n` +
`π¬ *Message:* ${reservation.message || 'None'}`
);
return `https://wa.me/${OWNER_PHONE?.replace(/[^0-9]/g, '')}?text=${message}`;
},
/**
* Try email first, fall back to WhatsApp if fails
* @param {Object} reservation - Reservation data
*/
async notifyWithFallback(reservation) {
try {
const result = await this.onNewReservation(reservation);
if (result.ownerNotification?.error) {
throw new Error(result.ownerNotification.error);
}
return { method: 'email', ...result };
} catch (error) {
console.warn('Email failed, using WhatsApp fallback');
const whatsappUrl = this.getWhatsAppFallback(reservation);
window.open(whatsappUrl, '_blank');
return { method: 'whatsapp', url: whatsappUrl };
}
},
// ==========================================
// Utility Functions
// ==========================================
/**
* Format date for display
* @param {string} dateStr - Date string
*/
formatDate(dateStr) {
const date = new Date(dateStr);
return date.toLocaleDateString('en-IN', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
},
/**
* Format time for display
* @param {string} timeStr - Time string
*/
formatTime(timeStr) {
if (!timeStr) return 'Not specified';
const [hours, minutes] = timeStr.split(':');
const hour = parseInt(hours);
const ampm = hour >= 12 ? 'PM' : 'AM';
const hour12 = hour % 12 || 12;
return `${hour12}:${minutes} ${ampm}`;
},
/**
* Log automation for debugging/analytics
* @param {string} type - Notification type
* @param {Object} reservation - Reservation data
* @param {Object} result - Automation result
*/
logAutomation(type, reservation, result) {
const log = {
type,
reservationId: reservation.id,
customerName: reservation.name,
result,
timestamp: new Date().toISOString()
};
// Store in localStorage for debugging
const logs = JSON.parse(localStorage.getItem('automation_logs') || '[]');
logs.push(log);
// Keep only last 100 logs
if (logs.length > 100) logs.shift();
localStorage.setItem('automation_logs', JSON.stringify(logs));
console.log('π Automation logged:', log);
},
/**
* Get automation logs
*/
getLogs() {
return JSON.parse(localStorage.getItem('automation_logs') || '[]');
},
/**
* Clear automation logs
*/
clearLogs() {
localStorage.removeItem('automation_logs');
console.log('π§Ή Automation logs cleared');
}
};
// ==========================================
// Supabase Real-time Listener (Optional)
// Automatically triggers on new reservations
// ==========================================
function setupRealtimeAutomation() {
if (!supabase) {
console.warn('Supabase not initialized - real-time automation disabled');
return;
}
const channel = supabase
.channel('reservations-automation')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'reservations'
},
async (payload) => {
console.log('π Real-time: New reservation detected!');
await EmailAutomation.onNewReservation(payload.new);
}
)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'reservations'
},
async (payload) => {
const oldStatus = payload.old?.status;
const newStatus = payload.new?.status;
if (oldStatus !== newStatus) {
console.log(`π Real-time: Status changed from ${oldStatus} to ${newStatus}`);
await EmailAutomation.sendStatusUpdate(payload.new, newStatus);
}
}
)
.subscribe();
console.log('β
Real-time automation listener active');
return channel;
}
// ==========================================
// Auto-initialize on page load
// ==========================================
document.addEventListener('DOMContentLoaded', () => {
// Initialize email automation
EmailAutomation.init();
// Setup real-time listener if Supabase is available
if (typeof initSupabase === 'function') {
initSupabase();
setTimeout(setupRealtimeAutomation, 1000); // Wait for Supabase to init
}
});
// ==========================================
// Export for use in other files
// ==========================================
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
EmailAutomation,
setupRealtimeAutomation,
NOTIFICATION_TYPES
};
}