1- import {
2- brevoApiInstance ,
3- brevoSendSmtpEmail ,
4- } from "../config/setupEmailNotificationService" ;
5- import { TEST_NOTIFICATIONS } from "../constants/constants" ;
1+ import { TEST_DATE_NOW , TEST_NOTIFICATIONS } from "../constants/constants" ;
62import { supabaseServersideClient } from "../db/setupDb" ;
73import { isDateBetween } from "../utils/compareDates" ;
4+ import axios from "axios" ;
5+
6+ type EmaiLData = {
7+ sender : {
8+ email : string ;
9+ name : string ;
10+ } ;
11+ to : {
12+ email : string ;
13+ name : string ;
14+ } [ ] ;
15+ subject : string ;
16+ htmlContent : string ;
17+ } ;
18+
19+ // Create a function to send emails via Brevo API
20+ async function sendBrevoEmail ( emailData : EmaiLData ) {
21+ try {
22+ const response = await axios ( {
23+ method : "post" ,
24+ url : "https://api.brevo.com/v3/smtp/email" ,
25+ headers : {
26+ accept : "application/json" ,
27+ "Api-key" : process . env . BREVO_API_KEY ! ,
28+ "content-type" : "application/json" ,
29+ } ,
30+ data : emailData ,
31+ } ) ;
32+
33+ return response ?. data ;
34+ } catch ( error : any ) {
35+ console . error (
36+ "Error sending email:" ,
37+ error ?. response ? error ?. response ?. data : error ?. message
38+ ) ;
39+ throw error ;
40+ }
41+ }
842
943// Ensure offering is in current semester and current day of week
1044export function correctDay ( offering : any ) : boolean {
@@ -14,30 +48,37 @@ export function correctDay(offering: any): boolean {
1448
1549 if ( ! semester || ! day ) return false ;
1650
17- const now = new Date ( ) ;
51+ let now ;
52+ if ( TEST_NOTIFICATIONS ) {
53+ now = TEST_DATE_NOW ;
54+ } else {
55+ now = new Date ( ) ;
56+ }
1857
1958 let startDay ;
2059 let endDay ;
2160
61+ // console.log(offering)
62+
2263 if ( semester === "Summer 2025" ) {
23- startDay = new Date ( 2025 , 5 , 2 ) ;
24- endDay = new Date ( 2025 , 8 , 7 ) ;
64+ startDay = new Date ( 2025 , 4 , 2 ) ;
65+ endDay = new Date ( 2025 , 7 , 7 ) ;
2566 } else if ( semester === "Fall 2025" ) {
26- startDay = new Date ( 2025 , 9 , 3 ) ;
27- endDay = new Date ( 2025 , 12 , 3 ) ;
67+ startDay = new Date ( 2025 , 8 , 3 ) ;
68+ endDay = new Date ( 2025 , 11 , 3 ) ;
2869 } else {
2970 // Winter 2026
30- startDay = new Date ( 2026 , 1 , 6 ) ;
31- endDay = new Date ( 2026 , 4 , 4 ) ;
71+ startDay = new Date ( 2026 , 0 , 6 ) ;
72+ endDay = new Date ( 2026 , 3 , 4 ) ;
3273 }
3374
3475 if ( ! isDateBetween ( now , startDay , endDay ) ) {
35- console . log ( `${ now . toDateString ( ) } is not between ${ startDay . toDateString ( ) } and ${ endDay . toDateString ( ) } ` )
76+ // console.log(`${now.toDateString()} is not between ${startDay.toDateString()} and ${endDay.toDateString()}`)
3677 return false ;
3778 }
3879
3980 if ( weekdays [ now . getDay ( ) ] !== day ) {
40- console . log ( `${ weekdays [ now . getDay ( ) ] } is not equal to ${ day } ` )
81+ // console.log(`${weekdays[now.getDay()]} is not equal to ${day}`)
4182 return false ;
4283 }
4384
@@ -49,9 +90,8 @@ export async function checkAndNotifyEvents() {
4990 console . log ( "Checking for upcoming events..." ) ;
5091 let now ;
5192 if ( TEST_NOTIFICATIONS ) {
52- now = new Date ( 2025 , 7 , 5 , 18 , 45 , 1 ) ;
53- }
54- else {
93+ now = TEST_DATE_NOW ;
94+ } else {
5595 now = new Date ( ) ;
5696 }
5797
@@ -68,7 +108,7 @@ export async function checkAndNotifyEvents() {
68108 . from ( "course_events" )
69109 . select ( "*" )
70110 . gte ( "event_start" , formattedStartTime )
71- . lte ( "event_end " , formattedEndTime ) ;
111+ . lte ( "event_start " , formattedEndTime ) ;
72112
73113 if ( error ) {
74114 console . error ( "Error fetching events:" , error ) ;
@@ -80,20 +120,21 @@ export async function checkAndNotifyEvents() {
80120 // Send email notifications for each event
81121 for ( const event of events ) {
82122 // Get offering
83- const { data : offerings , error : errorOffering } = await supabaseServersideClient
84- . schema ( "course" )
85- . from ( "offerings" )
86- . select ( "*" )
87- . eq ( "id" , event . offering_id )
88- . limit ( 1 ) ;
123+ const { data : offerings , error : errorOffering } =
124+ await supabaseServersideClient
125+ . schema ( "course" )
126+ . from ( "offerings" )
127+ . select ( "*" )
128+ . eq ( "id" , event . offering_id )
129+ . limit ( 1 ) ;
89130
90131 if ( errorOffering ) {
91- console . error ( "Error fetching user : " , errorOffering ) ;
132+ console . error ( "Error fetching offering : " , errorOffering ) ;
92133 return ;
93134 }
94135
95136 if ( ! offerings || offerings . length === 0 ) {
96- console . error ( "Error fetching offeirng: " , errorOffering ) ;
137+ console . error ( "Offering not found id: " , event . offering_id ) ;
97138 return ;
98139 }
99140
@@ -103,59 +144,49 @@ export async function checkAndNotifyEvents() {
103144 }
104145
105146 // Get user info
106- const { data : users , error } = await supabaseServersideClient
107- . schema ( "auth" )
108- . from ( "users" )
109- . select ( "*" )
110- . eq ( "id" , event . user_id )
111- . limit ( 1 ) ;
147+ const { data : userData , error } =
148+ await supabaseServersideClient . auth . admin . getUserById ( event . user_id ) ;
112149
113150 if ( error ) {
114151 console . error ( "Error fetching user: " , error ) ;
115152 return ;
116153 }
117154
118- if ( ! users || users . length === 0 ) {
119- console . error ( "User not found" ) ;
155+ if ( ! userData ) {
156+ console . error ( "User not found id:" , event . user_id ) ;
120157 return ;
121158 }
122159
123- const user = users [ 0 ] ;
160+ const user = userData ?. user ;
124161 const userEmail = user ?. email ;
125- const userName = user ?. raw_user_meta_data ?. username ;
126-
127- // Prepare email content
128- brevoSendSmtpEmail . to = [ { email : userEmail , name : userName } ] ;
129- brevoSendSmtpEmail . sender = {
130- email : process . env . SENDER_EMAIL ,
131- name : process . env . SENDER_NAME || "Course Matrix Notifications" ,
132- } ;
133- brevoSendSmtpEmail . subject = `Reminder: ${ event . event_name } starting soon` ;
134- brevoSendSmtpEmail . htmlContent = `
135- <h2>Event Reminder</h2>
136- <p>Hello ${ userName } ,</p>
137- <p>Your event "${
138- event . event_name
139- } " is starting in approximately 15 minutes.</p>
140- <p><strong>Start time:</strong> ${ new Date (
141- event . event_start
142- ) . toLocaleString ( ) } </p>
143- <p><strong>Description:</strong> ${
144- event . event_description || "No description provided"
145- } </p>
146- <p>Thank you for using our calendar service!</p>
147- ` ;
148-
149- // Send email
162+ const userName = user ?. user_metadata ?. username ;
163+
164+ console . log ( `Sending email to ${ userEmail } for ${ event . event_name } ` ) ;
165+
150166 try {
151- const data = await brevoApiInstance . sendTransacEmail (
152- brevoSendSmtpEmail
153- ) ;
154- console . log (
155- `Email sent to ${ userEmail } for event ${ event . id } . Message ID: ${ data . messageId } `
156- ) ;
157- } catch ( emailError ) {
158- console . error ( "Error sending email with Brevo:" , emailError ) ;
167+ const email = {
168+ sender : {
169+ email : process . env . SENDER_EMAIL ! ,
170+ name : process . env . SENDER_NAME || "Course Matrix Notifications" ,
171+ } ,
172+ to : [ { email : userEmail ! , name : userName } ] ,
173+ subject : `Reminder: ${ event . event_name } starting soon` ,
174+ htmlContent : `
175+ <h2>Event Reminder</h2>
176+ <p>Hello ${ userName } ,</p>
177+ <p>Your event "${ event . event_name } " is starting soon</p>
178+ <p><strong>Start time:</strong> ${ event . event_start } </p>
179+ <p><strong>Description:</strong> ${
180+ event . event_description || "No description provided"
181+ } </p>
182+ <p>Thank you for using our calendar service!</p>
183+ ` ,
184+ } ;
185+
186+ const result = await sendBrevoEmail ( email ) ;
187+ console . log ( "Email sent successfully:" , result ) ;
188+ } catch ( error ) {
189+ console . error ( "Failed to send email:" , error ) ;
159190 }
160191 }
161192 } catch ( err ) {
0 commit comments